Spaces:
Sleeping
Sleeping
Update app_logic.py
Browse files- app_logic.py +27 -39
app_logic.py
CHANGED
|
@@ -7,7 +7,6 @@ import logging
|
|
| 7 |
from pathlib import Path
|
| 8 |
from PIL import Image
|
| 9 |
|
| 10 |
-
# Import the extractor logic
|
| 11 |
from keylock import core as keylock_core
|
| 12 |
|
| 13 |
logging.basicConfig(
|
|
@@ -16,23 +15,41 @@ logging.basicConfig(
|
|
| 16 |
)
|
| 17 |
logger = logging.getLogger(__name__)
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
def _get_api_token(ui_token_from_textbox=None):
|
| 20 |
-
"""Helper to get the API token from UI input or environment variables."""
|
| 21 |
env_token = os.getenv('HF_TOKEN')
|
| 22 |
if env_token: return env_token, None
|
| 23 |
if ui_token_from_textbox: return ui_token_from_textbox, None
|
| 24 |
return None, "Error: Hugging Face API token not provided."
|
| 25 |
|
| 26 |
def extract_markdown_from_image(repo_image: Image.Image, image_password: str):
|
| 27 |
-
"""
|
| 28 |
-
A wrapper function to call the keylock core extractor.
|
| 29 |
-
Returns the markdown string on success, or an error message on failure.
|
| 30 |
-
"""
|
| 31 |
if not repo_image:
|
| 32 |
return None, "Error: Please upload a repository image."
|
| 33 |
-
|
| 34 |
password_to_use = image_password if image_password is not None else ""
|
| 35 |
-
|
| 36 |
try:
|
| 37 |
logger.info("Starting extraction of markdown from image...")
|
| 38 |
result = keylock_core.extract_repo_from_image(repo_image, password_to_use)
|
|
@@ -46,16 +63,10 @@ def extract_markdown_from_image(repo_image: Image.Image, image_password: str):
|
|
| 46 |
return None, f"Error during extraction: {e}"
|
| 47 |
|
| 48 |
def parse_markdown(markdown_input):
|
| 49 |
-
"""
|
| 50 |
-
Parses the repo markdown string to get file structure and content.
|
| 51 |
-
This function remains the same.
|
| 52 |
-
"""
|
| 53 |
space_info = {"files": []}
|
| 54 |
current_file_path = None; current_file_content_lines = []
|
| 55 |
in_file_definition = False; in_code_block = False
|
| 56 |
-
|
| 57 |
lines = markdown_input.strip().split("\n")
|
| 58 |
-
|
| 59 |
for line_content_orig in lines:
|
| 60 |
line_content_stripped = line_content_orig.strip()
|
| 61 |
if line_content_stripped.startswith("### File:"):
|
|
@@ -64,23 +75,19 @@ def parse_markdown(markdown_input):
|
|
| 64 |
current_file_path = line_content_stripped.replace("### File:", "").strip()
|
| 65 |
current_file_content_lines = []; in_file_definition = True; in_code_block = False
|
| 66 |
continue
|
| 67 |
-
if not in_file_definition:
|
| 68 |
-
continue
|
| 69 |
if line_content_stripped.startswith("```"):
|
| 70 |
in_code_block = not in_code_block
|
| 71 |
continue
|
| 72 |
current_file_content_lines.append(line_content_orig)
|
| 73 |
if current_file_path and in_file_definition:
|
| 74 |
space_info["files"].append({"path": current_file_path, "content": "\n".join(current_file_content_lines)})
|
| 75 |
-
|
| 76 |
space_info["files"] = [f for f in space_info["files"] if f.get("path")]
|
| 77 |
return space_info
|
| 78 |
|
| 79 |
def _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui):
|
| 80 |
-
"""Determines the final repo_id (owner/space_name)."""
|
| 81 |
if not space_name_ui: return None, "Error: Space Name cannot be empty."
|
| 82 |
if "/" in space_name_ui: return None, "Error: Space Name should not contain '/'. Use the Owner field."
|
| 83 |
-
|
| 84 |
final_owner = owner_ui
|
| 85 |
if not final_owner:
|
| 86 |
resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
|
|
@@ -90,25 +97,17 @@ def _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui):
|
|
| 90 |
final_owner = user_info.get('name')
|
| 91 |
except Exception as e:
|
| 92 |
return None, f"Error retrieving username from token: {e}. Please specify the Owner manually."
|
| 93 |
-
|
| 94 |
if not final_owner: return None, "Error: Owner could not be determined."
|
| 95 |
return f"{final_owner}/{space_name_ui}", None
|
| 96 |
|
| 97 |
def create_space(ui_api_token_from_textbox, space_name_ui, owner_ui, sdk_ui, markdown_input):
|
| 98 |
-
"""
|
| 99 |
-
The core function to create the space from the markdown string.
|
| 100 |
-
This function remains largely the same.
|
| 101 |
-
"""
|
| 102 |
repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
|
| 103 |
if err: return err
|
| 104 |
-
|
| 105 |
try:
|
| 106 |
resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
|
| 107 |
if token_err: return token_err
|
| 108 |
-
|
| 109 |
space_info = parse_markdown(markdown_input)
|
| 110 |
if not space_info["files"]: return "Error: No files were found after parsing the markdown from the image."
|
| 111 |
-
|
| 112 |
with tempfile.TemporaryDirectory() as temp_dir:
|
| 113 |
repo_staging_path = Path(temp_dir) / "repo_staging"
|
| 114 |
repo_staging_path.mkdir()
|
|
@@ -117,11 +116,7 @@ def create_space(ui_api_token_from_textbox, space_name_ui, owner_ui, sdk_ui, mar
|
|
| 117 |
file_path_abs.parent.mkdir(parents=True, exist_ok=True)
|
| 118 |
with open(file_path_abs, "w", encoding="utf-8") as f:
|
| 119 |
f.write(file_info["content"])
|
| 120 |
-
|
| 121 |
-
# Create the repo
|
| 122 |
create_repo(repo_id=repo_id, token=resolved_api_token, repo_type="space", space_sdk=sdk_ui, exist_ok=True)
|
| 123 |
-
|
| 124 |
-
# Upload the contents
|
| 125 |
upload_folder(
|
| 126 |
repo_id=repo_id,
|
| 127 |
folder_path=str(repo_staging_path),
|
|
@@ -130,21 +125,14 @@ def create_space(ui_api_token_from_textbox, space_name_ui, owner_ui, sdk_ui, mar
|
|
| 130 |
repo_type="space",
|
| 131 |
commit_message="Initial Space creation from repo-embedded image"
|
| 132 |
)
|
| 133 |
-
|
| 134 |
return f"**Success!** Space created or updated: [{repo_id}](https://huggingface.co/spaces/{repo_id})"
|
| 135 |
except Exception as e:
|
| 136 |
logger.exception(f"Error in create_space for {repo_id}:")
|
| 137 |
return f"Error during Space creation: {str(e)}"
|
| 138 |
|
| 139 |
def build_space_from_image(api_token, repo_image, image_password, new_space_name, owner, sdk):
|
| 140 |
-
"""
|
| 141 |
-
The main orchestrator function called by the Gradio UI.
|
| 142 |
-
"""
|
| 143 |
-
# 1. Extract markdown from the image
|
| 144 |
markdown_string, error = extract_markdown_from_image(repo_image, image_password)
|
| 145 |
if error:
|
| 146 |
-
return error
|
| 147 |
-
|
| 148 |
-
# 2. Create the space using the extracted markdown
|
| 149 |
result = create_space(api_token, new_space_name, owner, sdk, markdown_string)
|
| 150 |
return result
|
|
|
|
| 7 |
from pathlib import Path
|
| 8 |
from PIL import Image
|
| 9 |
|
|
|
|
| 10 |
from keylock import core as keylock_core
|
| 11 |
|
| 12 |
logging.basicConfig(
|
|
|
|
| 15 |
)
|
| 16 |
logger = logging.getLogger(__name__)
|
| 17 |
|
| 18 |
+
# --- NEW FUNCTION TO GET USERNAME ---
|
| 19 |
+
def get_username_from_token(api_token: str):
|
| 20 |
+
"""
|
| 21 |
+
Fetches the username associated with a Hugging Face API token.
|
| 22 |
+
Returns the username on success, or an empty string on failure.
|
| 23 |
+
"""
|
| 24 |
+
if not api_token:
|
| 25 |
+
logger.info("API token is empty, cannot fetch username.")
|
| 26 |
+
return ""
|
| 27 |
+
|
| 28 |
+
try:
|
| 29 |
+
logger.info("Attempting to fetch username from provided API token.")
|
| 30 |
+
user_info = whoami(token=api_token)
|
| 31 |
+
username = user_info.get('name')
|
| 32 |
+
|
| 33 |
+
if username:
|
| 34 |
+
logger.info(f"Successfully fetched username: {username}")
|
| 35 |
+
return username
|
| 36 |
+
else:
|
| 37 |
+
logger.warning("Token was valid, but no username found in whoami() response.")
|
| 38 |
+
return "" # Return empty if name key doesn't exist
|
| 39 |
+
except Exception as e:
|
| 40 |
+
logger.error(f"Failed to validate token and fetch username: {e}")
|
| 41 |
+
return ""
|
| 42 |
+
|
| 43 |
def _get_api_token(ui_token_from_textbox=None):
|
|
|
|
| 44 |
env_token = os.getenv('HF_TOKEN')
|
| 45 |
if env_token: return env_token, None
|
| 46 |
if ui_token_from_textbox: return ui_token_from_textbox, None
|
| 47 |
return None, "Error: Hugging Face API token not provided."
|
| 48 |
|
| 49 |
def extract_markdown_from_image(repo_image: Image.Image, image_password: str):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
if not repo_image:
|
| 51 |
return None, "Error: Please upload a repository image."
|
|
|
|
| 52 |
password_to_use = image_password if image_password is not None else ""
|
|
|
|
| 53 |
try:
|
| 54 |
logger.info("Starting extraction of markdown from image...")
|
| 55 |
result = keylock_core.extract_repo_from_image(repo_image, password_to_use)
|
|
|
|
| 63 |
return None, f"Error during extraction: {e}"
|
| 64 |
|
| 65 |
def parse_markdown(markdown_input):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
space_info = {"files": []}
|
| 67 |
current_file_path = None; current_file_content_lines = []
|
| 68 |
in_file_definition = False; in_code_block = False
|
|
|
|
| 69 |
lines = markdown_input.strip().split("\n")
|
|
|
|
| 70 |
for line_content_orig in lines:
|
| 71 |
line_content_stripped = line_content_orig.strip()
|
| 72 |
if line_content_stripped.startswith("### File:"):
|
|
|
|
| 75 |
current_file_path = line_content_stripped.replace("### File:", "").strip()
|
| 76 |
current_file_content_lines = []; in_file_definition = True; in_code_block = False
|
| 77 |
continue
|
| 78 |
+
if not in_file_definition: continue
|
|
|
|
| 79 |
if line_content_stripped.startswith("```"):
|
| 80 |
in_code_block = not in_code_block
|
| 81 |
continue
|
| 82 |
current_file_content_lines.append(line_content_orig)
|
| 83 |
if current_file_path and in_file_definition:
|
| 84 |
space_info["files"].append({"path": current_file_path, "content": "\n".join(current_file_content_lines)})
|
|
|
|
| 85 |
space_info["files"] = [f for f in space_info["files"] if f.get("path")]
|
| 86 |
return space_info
|
| 87 |
|
| 88 |
def _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui):
|
|
|
|
| 89 |
if not space_name_ui: return None, "Error: Space Name cannot be empty."
|
| 90 |
if "/" in space_name_ui: return None, "Error: Space Name should not contain '/'. Use the Owner field."
|
|
|
|
| 91 |
final_owner = owner_ui
|
| 92 |
if not final_owner:
|
| 93 |
resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
|
|
|
|
| 97 |
final_owner = user_info.get('name')
|
| 98 |
except Exception as e:
|
| 99 |
return None, f"Error retrieving username from token: {e}. Please specify the Owner manually."
|
|
|
|
| 100 |
if not final_owner: return None, "Error: Owner could not be determined."
|
| 101 |
return f"{final_owner}/{space_name_ui}", None
|
| 102 |
|
| 103 |
def create_space(ui_api_token_from_textbox, space_name_ui, owner_ui, sdk_ui, markdown_input):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
|
| 105 |
if err: return err
|
|
|
|
| 106 |
try:
|
| 107 |
resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
|
| 108 |
if token_err: return token_err
|
|
|
|
| 109 |
space_info = parse_markdown(markdown_input)
|
| 110 |
if not space_info["files"]: return "Error: No files were found after parsing the markdown from the image."
|
|
|
|
| 111 |
with tempfile.TemporaryDirectory() as temp_dir:
|
| 112 |
repo_staging_path = Path(temp_dir) / "repo_staging"
|
| 113 |
repo_staging_path.mkdir()
|
|
|
|
| 116 |
file_path_abs.parent.mkdir(parents=True, exist_ok=True)
|
| 117 |
with open(file_path_abs, "w", encoding="utf-8") as f:
|
| 118 |
f.write(file_info["content"])
|
|
|
|
|
|
|
| 119 |
create_repo(repo_id=repo_id, token=resolved_api_token, repo_type="space", space_sdk=sdk_ui, exist_ok=True)
|
|
|
|
|
|
|
| 120 |
upload_folder(
|
| 121 |
repo_id=repo_id,
|
| 122 |
folder_path=str(repo_staging_path),
|
|
|
|
| 125 |
repo_type="space",
|
| 126 |
commit_message="Initial Space creation from repo-embedded image"
|
| 127 |
)
|
|
|
|
| 128 |
return f"**Success!** Space created or updated: [{repo_id}](https://huggingface.co/spaces/{repo_id})"
|
| 129 |
except Exception as e:
|
| 130 |
logger.exception(f"Error in create_space for {repo_id}:")
|
| 131 |
return f"Error during Space creation: {str(e)}"
|
| 132 |
|
| 133 |
def build_space_from_image(api_token, repo_image, image_password, new_space_name, owner, sdk):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
markdown_string, error = extract_markdown_from_image(repo_image, image_password)
|
| 135 |
if error:
|
| 136 |
+
return error
|
|
|
|
|
|
|
| 137 |
result = create_space(api_token, new_space_name, owner, sdk, markdown_string)
|
| 138 |
return result
|