broadfield-dev commited on
Commit
849764e
·
verified ·
1 Parent(s): 55a84a4

Update app_logic.py

Browse files
Files changed (1) hide show
  1. app_logic.py +73 -126
app_logic.py CHANGED
@@ -1,12 +1,12 @@
1
  import os
2
  import re
3
  import tempfile
4
- import git # Used by Repository
5
  from huggingface_hub import (
6
  create_repo,
7
  upload_folder,
8
  list_repo_files,
9
- Repository, # Used in update_space_file
10
  whoami,
11
  )
12
  import logging
@@ -19,50 +19,30 @@ try:
19
  KEYLOCK_DECODE_AVAILABLE = True
20
  except ImportError:
21
  KEYLOCK_DECODE_AVAILABLE = False
22
- decode_from_image_pil = None # Placeholder
23
  logging.warning("keylock-decode library not found. Image decoding feature will be disabled.")
24
 
25
-
26
- # Configure logging (ensure this is suitable for your environment, might be set in app.py too)
27
- # If keylock-decode uses its own logger (e.g., logging.getLogger('keylock_decode')),
28
- # you might need to adjust its level separately if you want more/less verbose output from it.
29
  logging.basicConfig(
30
  level=logging.INFO,
31
  format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
32
  )
33
  logger = logging.getLogger(__name__)
34
- if KEYLOCK_DECODE_AVAILABLE: # Example: Set keylock_decode's logger to DEBUG if you want its verbose output
35
- # logging.getLogger('keylock_decode.decoder').setLevel(logging.DEBUG) # Check actual logger name in keylock-decode
36
- pass
37
 
38
 
39
- # --- New Helper Function to Get API Token ---
40
  def _get_api_token(ui_token_from_textbox=None):
41
- """
42
- Retrieves the Hugging Face API token.
43
- Prioritizes HF_TOKEN from environment variables (potentially set by KeyLock-Decode),
44
- then falls back to UI input.
45
- Returns (token, error_message)
46
- """
47
  env_token = os.getenv('HF_TOKEN')
48
  if env_token:
49
  logger.info("Using HF_TOKEN from environment.")
50
  return env_token, None
51
-
52
  if ui_token_from_textbox:
53
  logger.info("Using API token from UI textbox.")
54
  return ui_token_from_textbox, None
55
-
56
  logger.warning("HF API token not found in environment or UI textbox.")
57
  return None, "Error: Hugging Face API token not provided. Please enter it in the textbox or load it from an image."
58
 
59
-
60
- # --- New Function for KeyLock-Decode Integration ---
61
  def load_token_from_image_and_set_env(image_pil_object: Image.Image, password: str):
62
- """
63
- Decodes data from a PIL Image object using keylock-decode, sets environment variables,
64
- and returns status messages.
65
- """
66
  if not KEYLOCK_DECODE_AVAILABLE:
67
  return "Error: KeyLock-Decode library is not installed. This feature is disabled."
68
 
@@ -73,13 +53,46 @@ def load_token_from_image_and_set_env(image_pil_object: Image.Image, password: s
73
 
74
  status_messages_display = []
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  try:
77
  logger.info(f"Attempting to decode from image using KeyLock-Decode...")
78
- # decode_from_image_pil expects a PIL Image object
79
  decoded_data, status_msgs_from_lib = decode_from_image_pil(
80
- image_pil_object,
81
  password,
82
- set_environment_variables=True # CRITICAL: This sets os.environ
83
  )
84
 
85
  status_messages_display.extend(status_msgs_from_lib)
@@ -92,26 +105,26 @@ def load_token_from_image_and_set_env(image_pil_object: Image.Image, password: s
92
 
93
  if os.getenv('HF_TOKEN'):
94
  status_messages_display.append(f"\n**SUCCESS: HF_TOKEN was found and has been set in the current process environment.** It will be prioritized for operations.")
95
- elif 'HF_TOKEN' in decoded_data: # Should be rare if set_env_vars=True
96
  status_messages_display.append(f"\nWarning: HF_TOKEN was in decoded data but os.getenv('HF_TOKEN') is not picking it up. This is unexpected if 'set_environment_variables=True' worked.")
97
  else:
98
  status_messages_display.append("\nNote: HF_TOKEN was not specifically found in the decoded data from the image.")
99
- else:
100
- # This case is often covered by status_msgs_from_lib, but good to have a fallback.
101
- if not any("No payload data found" in msg for msg in status_msgs_from_lib):
102
- status_messages_display.append("No data was decoded, or the decoded data was empty.")
103
 
104
- except ValueError as e: # Specific errors from keylock-decode (e.g., bad password, corrupted data)
105
  logger.error(f"KeyLock-Decode ValueError: {e}")
106
- status_messages_display.append(f"**Decoding Error:** {e}")
107
  except Exception as e:
108
  logger.exception("An unexpected error occurred during image decoding with KeyLock-Decode:")
109
- status_messages_display.append(f"**An unexpected error occurred:** {str(e)}")
110
 
111
  return "\n".join(status_messages_display)
112
 
113
 
114
- # --- Original `parse_markdown` function (unchanged) ---
115
  def parse_markdown(markdown_input):
116
  """Parse markdown input to extract space details and file structure."""
117
  space_info = {"repo_name_md": "", "owner_md": "", "files": []}
@@ -181,161 +194,95 @@ def parse_markdown(markdown_input):
181
  space_info["files"] = [f for f in space_info["files"] if f.get("path")]
182
  return space_info
183
 
184
-
185
- # --- Updated `_determine_repo_id` to use `_get_api_token` ---
186
  def _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui):
187
  if not space_name_ui:
188
  return None, "Error: Space Name cannot be empty."
189
  if "/" in space_name_ui:
190
  return None, "Error: Space Name should not contain '/'. Please use the Owner field for the namespace."
191
 
192
- final_owner = owner_ui
193
- error_message = None
194
-
195
  if not final_owner:
196
- # Get the actual token to use for whoami
197
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
198
- if token_err:
199
- return None, token_err
200
- # If resolved_api_token is None here but token_err is None, it means _get_api_token had an issue not returning error string
201
- # which _get_api_token is designed not to do, it should always return error if no token.
202
- if not resolved_api_token:
203
- return None, "Error: API token is required to automatically determine owner when Owner field is empty (internal check failed)."
204
-
205
  try:
206
  user_info = whoami(token=resolved_api_token)
207
  if user_info and 'name' in user_info:
208
  final_owner = user_info['name']
209
  logger.info(f"Determined owner: {final_owner} using API token.")
210
  else:
211
- logger.error(f"whoami(token=...) returned: {user_info} - 'name' field missing or user_info is None.")
212
- error_message = "Error: Could not retrieve username from API token. Ensure token is valid and has 'Read profile' permissions. Or, specify Owner manually."
213
  except Exception as e:
214
- logger.error(f"Error calling whoami for owner: {str(e)}")
215
- error_message = f"Error retrieving username from API token: {str(e)}. Please specify Owner manually."
216
-
217
- if error_message:
218
- return None, error_message
219
-
220
- if not final_owner:
221
- return None, "Error: Owner could not be determined. Please provide an owner or ensure your API token is valid."
222
-
223
  return f"{final_owner}/{space_name_ui}", None
224
 
225
-
226
- # --- Updated Core Functions to use `_get_api_token` ---
227
-
228
  def create_space(ui_api_token_from_textbox, space_name_ui, owner_ui, sdk_ui, markdown_input):
229
  repo_id_for_error_logging = f"{owner_ui}/{space_name_ui}" if owner_ui else space_name_ui
230
  try:
231
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
232
- if token_err:
233
- return token_err
234
-
235
- # _determine_repo_id will also call _get_api_token internally if owner_ui is blank
236
  repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
237
- if err:
238
- return err
239
- repo_id_for_error_logging = repo_id # Update for more accurate logging if determination succeeds
240
-
241
  space_info = parse_markdown(markdown_input)
242
- if not space_info["files"]:
243
- return "Error: No files found in the markdown input. Ensure '### File: path/to/file.ext' markers are used correctly."
244
-
245
  with tempfile.TemporaryDirectory() as temp_dir:
246
  repo_local_path = Path(temp_dir) / "repo_upload_content"
247
  repo_local_path.mkdir(exist_ok=True)
248
-
249
  for file_info in space_info["files"]:
250
  if not file_info.get("path"): continue
251
  file_path_abs = repo_local_path / file_info["path"]
252
  file_path_abs.parent.mkdir(parents=True, exist_ok=True)
253
  with open(file_path_abs, "w", encoding="utf-8") as f: f.write(file_info["content"])
254
- logger.info(f"Wrote file: {file_path_abs}")
255
-
256
  try:
257
- create_repo(
258
- repo_id=repo_id, token=resolved_api_token, repo_type="space",
259
- space_sdk=sdk_ui, private=False,
260
- )
261
- logger.info(f"Created Space repo: {repo_id}")
262
  except Exception as e:
263
  err_str = str(e).lower()
264
- if "already exists" in err_str or "you already created this repo" in err_str or "exists" in err_str:
265
- logger.info(f"Space {repo_id} already exists. Proceeding to upload/update files.")
266
- else:
267
  return f"Error creating Space '{repo_id}': {str(e)}"
268
-
269
- upload_folder(
270
- repo_id=repo_id, folder_path=str(repo_local_path), path_in_repo=".",
271
- token=resolved_api_token, repo_type="space",
272
- commit_message=f"Initial Space setup of {repo_id} via Builder",
273
- )
274
- logger.info(f"Uploaded files to Space: {repo_id}")
275
  return f"Successfully created/updated Space: [{repo_id}](https://huggingface.co/spaces/{repo_id})"
276
-
277
  except Exception as e:
278
  logger.exception(f"Error in create_space for {repo_id_for_error_logging}:")
279
  return f"Error during Space creation/update: {str(e)}"
280
 
281
-
282
  def view_space_files(ui_api_token_from_textbox, space_name_ui, owner_ui):
283
  repo_id_for_error_logging = f"{owner_ui}/{space_name_ui}" if owner_ui else space_name_ui
284
  try:
285
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
286
- if token_err:
287
- return token_err
288
-
289
  repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
290
- if err:
291
- return err
292
  repo_id_for_error_logging = repo_id
293
-
294
  files = list_repo_files(repo_id=repo_id, token=resolved_api_token, repo_type="space")
295
- if files:
296
- return f"Files in `{repo_id}`:\n\n" + "\n".join([f"- `{f}`" for f in files])
297
- return f"No files found in the Space `{repo_id}`."
298
  except Exception as e:
299
  logger.exception(f"Error in view_space_files for {repo_id_for_error_logging}:")
300
  return f"Error listing files for `{repo_id_for_error_logging}`: {str(e)}"
301
 
302
-
303
  def update_space_file(ui_api_token_from_textbox, space_name_ui, owner_ui, file_path_in_repo, file_content, commit_message_ui):
304
  repo_id_for_error_logging = f"{owner_ui}/{space_name_ui}" if owner_ui else space_name_ui
305
  try:
306
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
307
- if token_err:
308
- return token_err
309
-
310
  repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
311
- if err:
312
- return err
313
  repo_id_for_error_logging = repo_id
314
-
315
  if not file_path_in_repo: return "Error: File Path cannot be empty."
316
  commit_message_ui = commit_message_ui or f"Update {file_path_in_repo} via Space Builder"
317
-
318
  with tempfile.TemporaryDirectory() as temp_dir:
319
  repo_local_clone_path = Path(temp_dir) / "cloned_space_repo_for_update"
320
-
321
- cloned_repo = Repository(
322
- local_dir=str(repo_local_clone_path),
323
- clone_from=f"https://huggingface.co/spaces/{repo_id}",
324
- repo_type="space", use_auth_token=resolved_api_token,
325
- git_user="Space Builder Bot", git_email="space-builder@huggingface.co"
326
- )
327
- logger.info(f"Cloned Space {repo_id} to {repo_local_clone_path}")
328
-
329
  full_local_file_path = Path(cloned_repo.local_dir) / file_path_in_repo
330
  full_local_file_path.parent.mkdir(parents=True, exist_ok=True)
331
  with open(full_local_file_path, "w", encoding="utf-8") as f: f.write(file_content)
332
- logger.info(f"Wrote updated file {file_path_in_repo} locally.")
333
-
334
  cloned_repo.push_to_hub(commit_message=commit_message_ui)
335
- logger.info(f"Pushed changes for {file_path_in_repo} to {repo_id}")
336
-
337
  return f"Successfully updated `{file_path_in_repo}` in Space [{repo_id}](https://huggingface.co/spaces/{repo_id})"
338
-
339
  except Exception as e:
340
  logger.exception(f"Error in update_space_file for {repo_id_for_error_logging}:")
341
  return f"Error updating file for `{repo_id_for_error_logging}`: {str(e)}"
 
1
  import os
2
  import re
3
  import tempfile
4
+ import git
5
  from huggingface_hub import (
6
  create_repo,
7
  upload_folder,
8
  list_repo_files,
9
+ Repository,
10
  whoami,
11
  )
12
  import logging
 
19
  KEYLOCK_DECODE_AVAILABLE = True
20
  except ImportError:
21
  KEYLOCK_DECODE_AVAILABLE = False
22
+ decode_from_image_pil = None
23
  logging.warning("keylock-decode library not found. Image decoding feature will be disabled.")
24
 
 
 
 
 
25
  logging.basicConfig(
26
  level=logging.INFO,
27
  format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
28
  )
29
  logger = logging.getLogger(__name__)
 
 
 
30
 
31
 
32
+ # --- Helper Function to Get API Token (Unchanged from previous version) ---
33
  def _get_api_token(ui_token_from_textbox=None):
 
 
 
 
 
 
34
  env_token = os.getenv('HF_TOKEN')
35
  if env_token:
36
  logger.info("Using HF_TOKEN from environment.")
37
  return env_token, None
 
38
  if ui_token_from_textbox:
39
  logger.info("Using API token from UI textbox.")
40
  return ui_token_from_textbox, None
 
41
  logger.warning("HF API token not found in environment or UI textbox.")
42
  return None, "Error: Hugging Face API token not provided. Please enter it in the textbox or load it from an image."
43
 
44
+ # --- Updated Function for KeyLock-Decode Integration with Debugging ---
 
45
  def load_token_from_image_and_set_env(image_pil_object: Image.Image, password: str):
 
 
 
 
46
  if not KEYLOCK_DECODE_AVAILABLE:
47
  return "Error: KeyLock-Decode library is not installed. This feature is disabled."
48
 
 
53
 
54
  status_messages_display = []
55
 
56
+ # --- DEBUGGING: Check image properties and save it ---
57
+ debug_image_path_str = "Not saved (error or no image)."
58
+ try:
59
+ if image_pil_object:
60
+ # Log original properties
61
+ original_mode = getattr(image_pil_object, 'mode', 'N/A')
62
+ original_format = getattr(image_pil_object, 'format', 'N/A') # Format might be None for PIL object not read from file
63
+ original_size = getattr(image_pil_object, 'size', 'N/A')
64
+ logger.info(f"Received PIL Image from Gradio. Mode: {original_mode}, Original Format: {original_format}, Size: {original_size}")
65
+ status_messages_display.append(f"[DEBUG] Gradio provided PIL Image - Mode: {original_mode}, Original Format: {original_format}, Size: {original_size}")
66
+
67
+ # Save the image received from Gradio to a temporary file for external checking
68
+ # Ensure the temp directory is writable in the Hugging Face Space environment
69
+ # /tmp/ is usually writable.
70
+ temp_dir = Path(tempfile.gettempdir()) / "gradio_image_debug"
71
+ temp_dir.mkdir(parents=True, exist_ok=True)
72
+ debug_image_path = temp_dir / "image_from_gradio.png"
73
+
74
+ # Save the image. If it's RGBA, try to keep it RGBA.
75
+ # PNG is lossless, so this should be okay if the mode is preserved.
76
+ image_pil_object.save(debug_image_path, "PNG")
77
+ debug_image_path_str = str(debug_image_path)
78
+ status_messages_display.append(f"**[DEBUG ACTION REQUIRED]** Image received from Gradio has been saved to: `{debug_image_path_str}` in the Space's temporary filesystem. Please try decoding this *specific file* using the standalone `keylock-decode` CLI to verify its integrity. E.g., `keylock-decode {debug_image_path_str} \"YOUR_PASSWORD\"`")
79
+ logger.info(f"Debug image from Gradio saved to: {debug_image_path_str}")
80
+ else:
81
+ logger.warning("image_pil_object is None when trying to debug-save.")
82
+ status_messages_display.append("[DEBUG] No PIL image object received to save for debugging.")
83
+
84
+ except Exception as save_exc:
85
+ logger.exception("Error during debug-saving of image from Gradio:")
86
+ status_messages_display.append(f"[DEBUG] Error saving image for debugging: {str(save_exc)}. Path was: {debug_image_path_str}")
87
+ # --- END DEBUGGING ---
88
+
89
  try:
90
  logger.info(f"Attempting to decode from image using KeyLock-Decode...")
91
+ # Pass the original PIL object
92
  decoded_data, status_msgs_from_lib = decode_from_image_pil(
93
+ image_pil_object, # Use the PIL object directly
94
  password,
95
+ set_environment_variables=True
96
  )
97
 
98
  status_messages_display.extend(status_msgs_from_lib)
 
105
 
106
  if os.getenv('HF_TOKEN'):
107
  status_messages_display.append(f"\n**SUCCESS: HF_TOKEN was found and has been set in the current process environment.** It will be prioritized for operations.")
108
+ elif 'HF_TOKEN' in decoded_data:
109
  status_messages_display.append(f"\nWarning: HF_TOKEN was in decoded data but os.getenv('HF_TOKEN') is not picking it up. This is unexpected if 'set_environment_variables=True' worked.")
110
  else:
111
  status_messages_display.append("\nNote: HF_TOKEN was not specifically found in the decoded data from the image.")
112
+ # else:
113
+ # if not any("No payload data found" in msg for msg in status_msgs_from_lib) and not any("Failed to decrypt" in msg for msg in status_msgs_from_lib): # Avoid redundant messages
114
+ # status_messages_display.append("No data was decoded, or the decoded data was empty (and no specific error from library).")
115
+
116
 
117
+ except ValueError as e:
118
  logger.error(f"KeyLock-Decode ValueError: {e}")
119
+ status_messages_display.append(f"**Decoding Error (e.g., bad password, corrupted data):** {e}")
120
  except Exception as e:
121
  logger.exception("An unexpected error occurred during image decoding with KeyLock-Decode:")
122
+ status_messages_display.append(f"**An unexpected error occurred during decoding:** {str(e)}")
123
 
124
  return "\n".join(status_messages_display)
125
 
126
 
127
+ # --- `parse_markdown` (Unchanged) ---
128
  def parse_markdown(markdown_input):
129
  """Parse markdown input to extract space details and file structure."""
130
  space_info = {"repo_name_md": "", "owner_md": "", "files": []}
 
194
  space_info["files"] = [f for f in space_info["files"] if f.get("path")]
195
  return space_info
196
 
197
+ # --- `_determine_repo_id` (Unchanged) ---
 
198
  def _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui):
199
  if not space_name_ui:
200
  return None, "Error: Space Name cannot be empty."
201
  if "/" in space_name_ui:
202
  return None, "Error: Space Name should not contain '/'. Please use the Owner field for the namespace."
203
 
204
+ final_owner = owner_ui; error_message = None
 
 
205
  if not final_owner:
 
206
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
207
+ if token_err: return None, token_err
208
+ if not resolved_api_token: return None, "Error: API token required for auto owner determination (internal check failed)."
 
 
 
 
 
209
  try:
210
  user_info = whoami(token=resolved_api_token)
211
  if user_info and 'name' in user_info:
212
  final_owner = user_info['name']
213
  logger.info(f"Determined owner: {final_owner} using API token.")
214
  else:
215
+ error_message = "Error: Could not retrieve username from API token. Check permissions or specify Owner."
 
216
  except Exception as e:
217
+ error_message = f"Error retrieving username from API token: {str(e)}. Specify Owner manually."
218
+ if error_message: return None, error_message
219
+ if not final_owner: return None, "Error: Owner could not be determined."
 
 
 
 
 
 
220
  return f"{final_owner}/{space_name_ui}", None
221
 
222
+ # --- Core Functions: `create_space`, `view_space_files`, `update_space_file` (Unchanged from previous correct version) ---
 
 
223
  def create_space(ui_api_token_from_textbox, space_name_ui, owner_ui, sdk_ui, markdown_input):
224
  repo_id_for_error_logging = f"{owner_ui}/{space_name_ui}" if owner_ui else space_name_ui
225
  try:
226
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
227
+ if token_err: return token_err
 
 
 
228
  repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
229
+ if err: return err
230
+ repo_id_for_error_logging = repo_id
 
 
231
  space_info = parse_markdown(markdown_input)
232
+ if not space_info["files"]: return "Error: No files found in markdown. Use '### File: path/to/file.ext'."
 
 
233
  with tempfile.TemporaryDirectory() as temp_dir:
234
  repo_local_path = Path(temp_dir) / "repo_upload_content"
235
  repo_local_path.mkdir(exist_ok=True)
 
236
  for file_info in space_info["files"]:
237
  if not file_info.get("path"): continue
238
  file_path_abs = repo_local_path / file_info["path"]
239
  file_path_abs.parent.mkdir(parents=True, exist_ok=True)
240
  with open(file_path_abs, "w", encoding="utf-8") as f: f.write(file_info["content"])
 
 
241
  try:
242
+ create_repo(repo_id=repo_id, token=resolved_api_token, repo_type="space", space_sdk=sdk_ui, private=False)
 
 
 
 
243
  except Exception as e:
244
  err_str = str(e).lower()
245
+ if not ("already exists" in err_str or "you already created this repo" in err_str or "exists" in err_str):
 
 
246
  return f"Error creating Space '{repo_id}': {str(e)}"
247
+ upload_folder(repo_id=repo_id, folder_path=str(repo_local_path), path_in_repo=".", token=resolved_api_token, repo_type="space", commit_message=f"Initial Space setup of {repo_id} via Builder")
 
 
 
 
 
 
248
  return f"Successfully created/updated Space: [{repo_id}](https://huggingface.co/spaces/{repo_id})"
 
249
  except Exception as e:
250
  logger.exception(f"Error in create_space for {repo_id_for_error_logging}:")
251
  return f"Error during Space creation/update: {str(e)}"
252
 
 
253
  def view_space_files(ui_api_token_from_textbox, space_name_ui, owner_ui):
254
  repo_id_for_error_logging = f"{owner_ui}/{space_name_ui}" if owner_ui else space_name_ui
255
  try:
256
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
257
+ if token_err: return token_err
 
 
258
  repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
259
+ if err: return err
 
260
  repo_id_for_error_logging = repo_id
 
261
  files = list_repo_files(repo_id=repo_id, token=resolved_api_token, repo_type="space")
262
+ if files: return f"Files in `{repo_id}`:\n\n" + "\n".join([f"- `{f}`" for f in files])
263
+ return f"No files found in Space `{repo_id}`."
 
264
  except Exception as e:
265
  logger.exception(f"Error in view_space_files for {repo_id_for_error_logging}:")
266
  return f"Error listing files for `{repo_id_for_error_logging}`: {str(e)}"
267
 
 
268
  def update_space_file(ui_api_token_from_textbox, space_name_ui, owner_ui, file_path_in_repo, file_content, commit_message_ui):
269
  repo_id_for_error_logging = f"{owner_ui}/{space_name_ui}" if owner_ui else space_name_ui
270
  try:
271
  resolved_api_token, token_err = _get_api_token(ui_api_token_from_textbox)
272
+ if token_err: return token_err
 
 
273
  repo_id, err = _determine_repo_id(ui_api_token_from_textbox, space_name_ui, owner_ui)
274
+ if err: return err
 
275
  repo_id_for_error_logging = repo_id
 
276
  if not file_path_in_repo: return "Error: File Path cannot be empty."
277
  commit_message_ui = commit_message_ui or f"Update {file_path_in_repo} via Space Builder"
 
278
  with tempfile.TemporaryDirectory() as temp_dir:
279
  repo_local_clone_path = Path(temp_dir) / "cloned_space_repo_for_update"
280
+ cloned_repo = Repository(local_dir=str(repo_local_clone_path), clone_from=f"https://huggingface.co/spaces/{repo_id}", repo_type="space", use_auth_token=resolved_api_token, git_user="Space Builder Bot", git_email="space-builder@huggingface.co")
 
 
 
 
 
 
 
 
281
  full_local_file_path = Path(cloned_repo.local_dir) / file_path_in_repo
282
  full_local_file_path.parent.mkdir(parents=True, exist_ok=True)
283
  with open(full_local_file_path, "w", encoding="utf-8") as f: f.write(file_content)
 
 
284
  cloned_repo.push_to_hub(commit_message=commit_message_ui)
 
 
285
  return f"Successfully updated `{file_path_in_repo}` in Space [{repo_id}](https://huggingface.co/spaces/{repo_id})"
 
286
  except Exception as e:
287
  logger.exception(f"Error in update_space_file for {repo_id_for_error_logging}:")
288
  return f"Error updating file for `{repo_id_for_error_logging}`: {str(e)}"