broadfield-dev commited on
Commit
52ce752
·
verified ·
1 Parent(s): 1a9c9d5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -25
app.py CHANGED
@@ -5,7 +5,8 @@ import os
5
  import uuid
6
  import shutil
7
  import tempfile
8
-
 
9
  # --- State Management and API Client ---
10
 
11
  def get_hf_api(token):
@@ -13,7 +14,29 @@ def get_hf_api(token):
13
  return HfApi(token=token if token else None)
14
 
15
  # --- Core Logic Functions ---
 
 
 
 
 
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  def handle_token_change(token):
18
  """
19
  Called when the token is entered. Fetches user info, updates UI interactivity,
@@ -112,10 +135,9 @@ def archive_repo(token, repo_id, archive_repo, manage_repo_type_state):
112
  # --- File Management Functions ---
113
 
114
  def show_files_and_load_first(token, repo_id, repo_type):
115
- """Lists files in a dropdown and pre-loads the first file's content."""
116
  if not repo_id:
117
- gr.Warning("No repository selected.")
118
- return gr.update(visible=False), gr.update(choices=[], value=None), gr.update(value="")
119
  try:
120
  api = get_hf_api(token)
121
  repo_files = api.list_repo_files(repo_id=repo_id, repo_type=repo_type)
@@ -123,16 +145,23 @@ def show_files_and_load_first(token, repo_id, repo_type):
123
 
124
  if not filtered_files:
125
  return (gr.update(visible=True), gr.update(choices=[], value=None),
126
- gr.update(value="## This repository is empty.", language='markdown'))
127
 
128
- first_file_path = filtered_files[0]
129
- content, language = load_file_content_backend(token, repo_id, repo_type, first_file_path)
130
-
131
- return (gr.update(visible=True), gr.update(choices=filtered_files, value=first_file_path),
132
- gr.update(value=content, language=language))
 
 
 
 
 
 
 
133
  except Exception as e:
134
- gr.Error(f"Could not manage files: {e}")
135
- return gr.update(visible=False), gr.update(choices=[], value=None), gr.update(value="")
136
 
137
  def load_file_content_backend(token, repo_id, repo_type, filepath):
138
  """Backend logic to fetch and format file content."""
@@ -150,21 +179,43 @@ def load_file_content_backend(token, repo_id, repo_type, filepath):
150
  return f"Error loading file: {e}", 'python'
151
 
152
  def load_file_content_for_editor(token, repo_id, repo_type, filepath):
153
- """Gradio wrapper to update the code editor when a file is selected."""
154
- content, language = load_file_content_backend(token, repo_id, repo_type, filepath)
155
- return gr.update(value=content, language=language)
 
 
 
 
 
 
156
 
157
- def commit_file(token, repo_id, repo_type, filepath, content, commit_message):
158
- """Commits a file to the repository."""
159
- if not token: gr.Error("A write-enabled token is required."); return
160
  if not filepath: gr.Warning("No file selected."); return
161
- if not commit_message: gr.Warning("Commit message cannot be empty."); return
162
  try:
163
  api = get_hf_api(token)
164
- api.upload_file(bytes(content, 'utf-8'), path_in_repo=filepath,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  repo_id=repo_id, repo_type=repo_type, commit_message=commit_message)
166
- gr.Info(f"Successfully committed '{filepath}' to '{repo_id}'!")
167
- except Exception as e: gr.Error(f"Failed to commit file: {e}")
168
 
169
  # --- Download Tab Functions ---
170
 
@@ -229,6 +280,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="Hugging Face Hub
229
  gr.Markdown("### 3. Edit Files")
230
  file_selector = gr.Dropdown(label="Select File", interactive=True)
231
  code_editor = gr.Code(label="File Content", interactive=True)
 
232
  commit_message_input = gr.Textbox(label="Commit Message", placeholder="e.g., Update README.md")
233
  commit_btn = gr.Button("Commit Changes", variant="primary", interactive=False)
234
  # Now, attach event handlers
@@ -261,7 +313,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="Hugging Face Hub
261
 
262
  manage_files_btn.click(fn=show_files_and_load_first,
263
  inputs=[hf_token_state, manage_repo_dropdown, manage_repo_type_state],
264
- outputs=[editor_panel, file_selector, code_editor])
 
265
 
266
  archive_repo_btn.click(fn=archive_repo, inputs=[hf_token_state, selected_repo, archive_repo_name, manage_repo_type_state],
267
  outputs=[manage_repo_dropdown, action_panel, editor_panel],
@@ -274,10 +327,14 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="Hugging Face Hub
274
 
275
  file_selector.change(fn=load_file_content_for_editor,
276
  inputs=[hf_token_state, manage_repo_dropdown, manage_repo_type_state, file_selector],
277
- outputs=code_editor)
 
278
 
279
  commit_btn.click(fn=commit_file,
280
- inputs=[hf_token_state, manage_repo_dropdown, manage_repo_type_state, file_selector, code_editor, commit_message_input])
 
 
 
281
 
282
  download_btn.click(fn=download_repos_as_zip,
283
  inputs=[hf_token_state, download_repo_dropdown, download_repo_type_state],
 
5
  import uuid
6
  import shutil
7
  import tempfile
8
+ import pandas as pd
9
+ import io
10
  # --- State Management and API Client ---
11
 
12
  def get_hf_api(token):
 
14
  return HfApi(token=token if token else None)
15
 
16
  # --- Core Logic Functions ---
17
+ def is_tabular(filepath):
18
+ """Checks if the file is a supported tabular dataset."""
19
+ if not filepath: return False
20
+ ext = os.path.splitext(filepath)[1].lower()
21
+ return ext in ['.csv', '.tsv', '.json', '.jsonl', '.parquet']
22
 
23
+ def load_tabular_content(token, repo_id, repo_type, filepath):
24
+ """Loads a file into a Pandas DataFrame."""
25
+ try:
26
+ api = get_hf_api(token)
27
+ local_path = api.hf_hub_download(repo_id=repo_id, repo_type=repo_type, filename=filepath, token=token)
28
+ ext = os.path.splitext(filepath)[1].lower()
29
+
30
+ if ext == '.csv': return pd.read_csv(local_path)
31
+ if ext == '.tsv': return pd.read_csv(local_path, sep='\t')
32
+ if ext == '.parquet': return pd.read_parquet(local_path)
33
+ if ext == '.json':
34
+ try: return pd.read_json(local_path)
35
+ except: return pd.read_json(local_path, lines=True) # Try JSONL
36
+ if ext == '.jsonl': return pd.read_json(local_path, lines=True)
37
+ return None
38
+ except Exception as e:
39
+ return pd.DataFrame({"Error": [str(e)]})
40
  def handle_token_change(token):
41
  """
42
  Called when the token is entered. Fetches user info, updates UI interactivity,
 
135
  # --- File Management Functions ---
136
 
137
  def show_files_and_load_first(token, repo_id, repo_type):
138
+ """Lists files and pre-loads the first one (Text OR DataFrame)."""
139
  if not repo_id:
140
+ return gr.update(visible=False), gr.update(choices=[], value=None), gr.update(visible=False), gr.update(visible=False)
 
141
  try:
142
  api = get_hf_api(token)
143
  repo_files = api.list_repo_files(repo_id=repo_id, repo_type=repo_type)
 
145
 
146
  if not filtered_files:
147
  return (gr.update(visible=True), gr.update(choices=[], value=None),
148
+ gr.update(value="## Empty Repo", visible=True), gr.update(visible=False))
149
 
150
+ first_file = filtered_files[0]
151
+
152
+ # Check type and load appropriately
153
+ if is_tabular(first_file):
154
+ df = load_tabular_content(token, repo_id, repo_type, first_file)
155
+ return (gr.update(visible=True), gr.update(choices=filtered_files, value=first_file),
156
+ gr.update(visible=False), gr.update(value=df, visible=True))
157
+ else:
158
+ content, lang = load_file_content_backend(token, repo_id, repo_type, first_file)
159
+ return (gr.update(visible=True), gr.update(choices=filtered_files, value=first_file),
160
+ gr.update(value=content, language=lang, visible=True), gr.update(visible=False))
161
+
162
  except Exception as e:
163
+ gr.Error(f"Error: {e}")
164
+ return gr.update(visible=False), gr.update(choices=[], value=None), gr.update(visible=True), gr.update(visible=False)
165
 
166
  def load_file_content_backend(token, repo_id, repo_type, filepath):
167
  """Backend logic to fetch and format file content."""
 
179
  return f"Error loading file: {e}", 'python'
180
 
181
  def load_file_content_for_editor(token, repo_id, repo_type, filepath):
182
+ """Decides whether to show the Code Editor or the Data Editor."""
183
+ if is_tabular(filepath):
184
+ df = load_tabular_content(token, repo_id, repo_type, filepath)
185
+ # Hide Code, Show DF
186
+ return gr.update(visible=False), gr.update(value=df, visible=True)
187
+ else:
188
+ content, language = load_file_content_backend(token, repo_id, repo_type, filepath)
189
+ # Show Code, Hide DF
190
+ return gr.update(value=content, language=language, visible=True), gr.update(visible=False)
191
 
192
+ def commit_file(token, repo_id, repo_type, filepath, code_content, df_content, commit_message):
193
+ """Smart commit: saves text OR dataframe based on file extension."""
194
+ if not token: gr.Error("Write-token required."); return
195
  if not filepath: gr.Warning("No file selected."); return
196
+
197
  try:
198
  api = get_hf_api(token)
199
+
200
+ if is_tabular(filepath):
201
+ # Handle DataFrame Saving
202
+ buffer = io.BytesIO()
203
+ ext = os.path.splitext(filepath)[1].lower()
204
+ if ext == '.csv': df_content.to_csv(buffer, index=False)
205
+ elif ext == '.tsv': df_content.to_csv(buffer, sep='\t', index=False)
206
+ elif ext == '.parquet': df_content.to_parquet(buffer, index=False)
207
+ elif ext == '.json': df_content.to_json(buffer, orient='records')
208
+ elif ext == '.jsonl': df_content.to_json(buffer, orient='records', lines=True)
209
+
210
+ data_to_upload = buffer.getvalue()
211
+ else:
212
+ # Handle Text Saving
213
+ data_to_upload = bytes(code_content, 'utf-8')
214
+
215
+ api.upload_file(path_or_fileobj=data_to_upload, path_in_repo=filepath,
216
  repo_id=repo_id, repo_type=repo_type, commit_message=commit_message)
217
+ gr.Info(f"Successfully committed '{filepath}'!")
218
+ except Exception as e: gr.Error(f"Failed to commit: {e}")
219
 
220
  # --- Download Tab Functions ---
221
 
 
280
  gr.Markdown("### 3. Edit Files")
281
  file_selector = gr.Dropdown(label="Select File", interactive=True)
282
  code_editor = gr.Code(label="File Content", interactive=True)
283
+ dataframe_editor = gr.Dataframe(label="Dataset Editor", interactive=True, visible=False, wrap=True)
284
  commit_message_input = gr.Textbox(label="Commit Message", placeholder="e.g., Update README.md")
285
  commit_btn = gr.Button("Commit Changes", variant="primary", interactive=False)
286
  # Now, attach event handlers
 
313
 
314
  manage_files_btn.click(fn=show_files_and_load_first,
315
  inputs=[hf_token_state, manage_repo_dropdown, manage_repo_type_state],
316
+ outputs=[editor_panel, file_selector, code_editor, dataframe_editor]) # Added dataframe_editor
317
+
318
 
319
  archive_repo_btn.click(fn=archive_repo, inputs=[hf_token_state, selected_repo, archive_repo_name, manage_repo_type_state],
320
  outputs=[manage_repo_dropdown, action_panel, editor_panel],
 
327
 
328
  file_selector.change(fn=load_file_content_for_editor,
329
  inputs=[hf_token_state, manage_repo_dropdown, manage_repo_type_state, file_selector],
330
+ outputs=[code_editor, dataframe_editor]) # Added dataframe_editor
331
+
332
 
333
  commit_btn.click(fn=commit_file,
334
+ inputs=[hf_token_state, manage_repo_dropdown, manage_repo_type_state, file_selector,
335
+ code_editor, dataframe_editor, # Added dataframe_editor
336
+ commit_message_input])
337
+
338
 
339
  download_btn.click(fn=download_repos_as_zip,
340
  inputs=[hf_token_state, download_repo_dropdown, download_repo_type_state],