Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -4,6 +4,16 @@ from flask import Flask, render_template_string, request, redirect, send_file, j
|
|
4 |
from huggingface_hub import HfApi, hf_hub_download, upload_file, delete_file, HfFolder
|
5 |
from urllib.parse import unquote, quote
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
# --- Environment Setup ---
|
8 |
# IMPORTANT: Set these environment variables before running the script.
|
9 |
# You can get a token from https://huggingface.co/settings/tokens
|
@@ -14,7 +24,7 @@ HF_TOKEN = os.getenv("HF_TOKEN")
|
|
14 |
# REPO_ID = "YourUsername/YourDatasetRepoName"
|
15 |
# HF_TOKEN = "hf_..."
|
16 |
|
17 |
-
# Ensure the hf_hub library uses the token
|
18 |
if HF_TOKEN:
|
19 |
HfFolder.save_token(HF_TOKEN)
|
20 |
|
@@ -530,7 +540,7 @@ def list_folder(path=""):
|
|
530 |
if dir_path not in seen_dirs:
|
531 |
seen_dirs.add(dir_path)
|
532 |
items.append({"type": "dir", "name": dir_name, "path": dir_path})
|
533 |
-
elif relative_path and relative_path != '.gitkeep':
|
534 |
items.append({"type": "file", "name": relative_path, "path": f})
|
535 |
|
536 |
items.sort(key=lambda x: (x["type"] != "dir", x["name"].lower()))
|
@@ -560,7 +570,8 @@ def index():
|
|
560 |
def download():
|
561 |
path = unquote(request.args.get("path", ""))
|
562 |
try:
|
563 |
-
|
|
|
564 |
return send_file(local_file, as_attachment=True, download_name=os.path.basename(path))
|
565 |
except Exception as e:
|
566 |
return f"Error downloading file: {e}", 500
|
@@ -586,24 +597,24 @@ def upload():
|
|
586 |
@app.route("/delete", methods=["POST"])
|
587 |
def delete():
|
588 |
path_to_delete = request.get_json()["path"].strip("/")
|
589 |
-
# Check if it's a file or folder by seeing if it has a '/' at the end of its relative path
|
590 |
all_repo_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset")
|
591 |
|
|
|
|
|
592 |
is_file = any(f == path_to_delete for f in all_repo_files)
|
593 |
|
594 |
if is_file:
|
595 |
delete_file(repo_id=REPO_ID, path_in_repo=path_to_delete, repo_type="dataset", commit_message=f"Delete file {path_to_delete}")
|
596 |
else: # It's a folder
|
597 |
-
# For folders, we need to delete all files within it.
|
598 |
-
# This is simpler with multiple calls than batching for this app.
|
599 |
files_in_folder = [f for f in all_repo_files if f.startswith(path_to_delete + "/")]
|
600 |
for f in files_in_folder:
|
601 |
-
delete_file(repo_id=REPO_ID, path_in_repo=f, repo_type="dataset", commit_message=f"Delete file {f} from folder")
|
602 |
-
#
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
|
|
607 |
|
608 |
return jsonify(status="ok")
|
609 |
|
@@ -613,7 +624,7 @@ def create_folder():
|
|
613 |
keep_file_path = f"{folder_path}/.gitkeep"
|
614 |
|
615 |
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".tmp") as tmp:
|
616 |
-
tmp.write("")
|
617 |
tmp_path = tmp.name
|
618 |
|
619 |
try:
|
@@ -635,21 +646,24 @@ def rename():
|
|
635 |
all_repo_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset")
|
636 |
is_file = any(f == old_path for f in all_repo_files)
|
637 |
|
638 |
-
|
639 |
if is_file:
|
640 |
-
|
641 |
else: # It's a folder
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
|
|
|
|
|
|
653 |
|
654 |
return jsonify(status="ok")
|
655 |
|
|
|
4 |
from huggingface_hub import HfApi, hf_hub_download, upload_file, delete_file, HfFolder
|
5 |
from urllib.parse import unquote, quote
|
6 |
|
7 |
+
# --- FIX FOR PERMISSION ERROR ---
|
8 |
+
# In restricted environments (like some containers), the default Hugging Face cache
|
9 |
+
# directory (~/.cache/huggingface) might not be writable. We override this by setting
|
10 |
+
# the HF_HOME environment variable to a writable directory.
|
11 |
+
# This must be done BEFORE any huggingface_hub functions are called.
|
12 |
+
HF_CACHE_DIR = os.path.join(tempfile.gettempdir(), "hf_home")
|
13 |
+
os.makedirs(HF_CACHE_DIR, exist_ok=True)
|
14 |
+
os.environ["HF_HOME"] = HF_CACHE_DIR
|
15 |
+
# --------------------------------
|
16 |
+
|
17 |
# --- Environment Setup ---
|
18 |
# IMPORTANT: Set these environment variables before running the script.
|
19 |
# You can get a token from https://huggingface.co/settings/tokens
|
|
|
24 |
# REPO_ID = "YourUsername/YourDatasetRepoName"
|
25 |
# HF_TOKEN = "hf_..."
|
26 |
|
27 |
+
# Ensure the hf_hub library uses the token. This will now write to the writable HF_HOME dir.
|
28 |
if HF_TOKEN:
|
29 |
HfFolder.save_token(HF_TOKEN)
|
30 |
|
|
|
540 |
if dir_path not in seen_dirs:
|
541 |
seen_dirs.add(dir_path)
|
542 |
items.append({"type": "dir", "name": dir_name, "path": dir_path})
|
543 |
+
elif relative_path and relative_path != '.gitkeep' and relative_path != '.keep':
|
544 |
items.append({"type": "file", "name": relative_path, "path": f})
|
545 |
|
546 |
items.sort(key=lambda x: (x["type"] != "dir", x["name"].lower()))
|
|
|
570 |
def download():
|
571 |
path = unquote(request.args.get("path", ""))
|
572 |
try:
|
573 |
+
# The HF_HOME env var automatically handles the cache location
|
574 |
+
local_file = hf_hub_download(repo_id=REPO_ID, filename=path, repo_type="dataset")
|
575 |
return send_file(local_file, as_attachment=True, download_name=os.path.basename(path))
|
576 |
except Exception as e:
|
577 |
return f"Error downloading file: {e}", 500
|
|
|
597 |
@app.route("/delete", methods=["POST"])
|
598 |
def delete():
|
599 |
path_to_delete = request.get_json()["path"].strip("/")
|
|
|
600 |
all_repo_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset")
|
601 |
|
602 |
+
# Check if the path is a file or a directory by looking for exact matches (file)
|
603 |
+
# vs. paths that start with the given path + "/" (directory)
|
604 |
is_file = any(f == path_to_delete for f in all_repo_files)
|
605 |
|
606 |
if is_file:
|
607 |
delete_file(repo_id=REPO_ID, path_in_repo=path_to_delete, repo_type="dataset", commit_message=f"Delete file {path_to_delete}")
|
608 |
else: # It's a folder
|
|
|
|
|
609 |
files_in_folder = [f for f in all_repo_files if f.startswith(path_to_delete + "/")]
|
610 |
for f in files_in_folder:
|
611 |
+
delete_file(repo_id=REPO_ID, path_in_repo=f, repo_type="dataset", commit_message=f"Delete file {f} from folder {path_to_delete}")
|
612 |
+
# Delete placeholder files if they exist to remove the empty folder
|
613 |
+
for placeholder in ['.gitkeep', '.keep']:
|
614 |
+
try:
|
615 |
+
delete_file(repo_id=REPO_ID, path_in_repo=f"{path_to_delete}/{placeholder}", repo_type="dataset", commit_message=f"Delete folder placeholder for {path_to_delete}", ignore_patterns=None)
|
616 |
+
except Exception:
|
617 |
+
pass # Placeholder did not exist, which is fine
|
618 |
|
619 |
return jsonify(status="ok")
|
620 |
|
|
|
624 |
keep_file_path = f"{folder_path}/.gitkeep"
|
625 |
|
626 |
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".tmp") as tmp:
|
627 |
+
tmp.write("") # Create an empty file
|
628 |
tmp_path = tmp.name
|
629 |
|
630 |
try:
|
|
|
646 |
all_repo_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset")
|
647 |
is_file = any(f == old_path for f in all_repo_files)
|
648 |
|
649 |
+
operations = []
|
650 |
if is_file:
|
651 |
+
operations.append((old_path, new_path))
|
652 |
else: # It's a folder
|
653 |
+
folder_prefix = old_path + "/"
|
654 |
+
for f in all_repo_files:
|
655 |
+
if f.startswith(folder_prefix):
|
656 |
+
new_file_path = new_path + f[len(old_path):]
|
657 |
+
operations.append((f, new_file_path))
|
658 |
+
|
659 |
+
for old_file, new_file in operations:
|
660 |
+
# This move is done server-side on the Hub, no local download needed
|
661 |
+
api.move_file(
|
662 |
+
from_path=old_file,
|
663 |
+
to_path=new_file,
|
664 |
+
repo_id=REPO_ID,
|
665 |
+
repo_type="dataset",
|
666 |
+
)
|
667 |
|
668 |
return jsonify(status="ok")
|
669 |
|