ChaosTong commited on
Commit
fa5ca94
·
verified ·
1 Parent(s): 24cc5fb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -152
app.py CHANGED
@@ -2,21 +2,9 @@ import gradio as gr
2
  import pandas as pd
3
  import json
4
  import os
5
- import tempfile
6
- from huggingface_hub import HfApi, upload_file, hf_hub_download
7
- import streamlit as st
8
 
9
  # --- Configuration & Helpers ---
10
- # 检查是否在 HF Spaces 环境中
11
- IS_HF_SPACE = os.getenv("SPACE_ID") is not None
12
-
13
- if IS_HF_SPACE:
14
- # HF Spaces 环境:使用临时目录
15
- DATA_DIR = tempfile.mkdtemp()
16
- print(f"Running in HF Spaces. Using temp directory: {DATA_DIR}")
17
- else:
18
- # 本地环境:使用当前目录
19
- DATA_DIR = '.'
20
 
21
  def find_json_files(directory):
22
  """Finds all .json files in the specified directory."""
@@ -26,32 +14,12 @@ def find_json_files(directory):
26
  except FileNotFoundError:
27
  return []
28
 
29
- def create_sample_files():
30
- """在 HF Spaces 环境中创建示例文件"""
31
- if IS_HF_SPACE:
32
- sample_data = [
33
- {"Name": "Sample1", "Title": "Example Title 1", "Params": "param1=value1"},
34
- {"Name": "Sample2", "Title": "Example Title 2", "Params": "param2=value2"}
35
- ]
36
-
37
- sample_file = os.path.join(DATA_DIR, "sample.json")
38
- try:
39
- with open(sample_file, 'w', encoding='utf-8') as f:
40
- json.dump(sample_data, f, indent=2, ensure_ascii=False)
41
- print(f"Created sample file: {sample_file}")
42
- except Exception as e:
43
- print(f"Error creating sample file: {e}")
44
-
45
- def refresh_file_list():
46
- """刷新文件列表,返回更新后的选择器"""
47
- available_files = find_json_files(DATA_DIR)
48
- return gr.Dropdown(choices=available_files)
49
-
50
  # --- Data Processing Functions ---
51
 
52
  def load_data(selected_file):
53
  """Loads data from the selected JSON file into a Pandas DataFrame."""
54
  if not selected_file:
 
55
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
56
  status = "Please select a JSON file from the dropdown to load."
57
  return df, status
@@ -59,21 +27,26 @@ def load_data(selected_file):
59
  file_path = os.path.join(DATA_DIR, selected_file)
60
 
61
  if not os.path.exists(file_path):
 
62
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
63
  status = f"Error: File '{selected_file}' not found in '{DATA_DIR}'."
64
  return df, status
65
  else:
66
  try:
 
67
  if os.path.getsize(file_path) == 0:
68
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
69
  status = f"'{selected_file}' is empty. Displaying empty table. You can add rows and save."
70
  return df, status
71
 
72
- df = pd.read_json(file_path, orient='records', dtype=str)
 
 
73
  df = df.reindex(columns=['Name', 'Title', 'Params'], fill_value='')
 
74
  df = df.fillna('')
75
  status = f"Data loaded successfully from '{selected_file}'."
76
- except ValueError as e:
77
  print(f"Error loading JSON from {selected_file}: {e}")
78
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
79
  status = f"Error loading '{selected_file}': Invalid JSON format or structure ({e}). Displaying empty table."
@@ -82,6 +55,7 @@ def load_data(selected_file):
82
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
83
  status = f"Unexpected error loading '{selected_file}': {e}. Displaying empty table."
84
 
 
85
  df['Name'] = df['Name'].astype(str)
86
  df['Title'] = df['Title'].astype(str)
87
  df['Params'] = df['Params'].astype(str)
@@ -91,17 +65,9 @@ def load_data(selected_file):
91
  def save_data_internal(data_list, file_path):
92
  """Writes a Python list to a specific JSON file path."""
93
  try:
94
- # 确保目录存在
95
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
96
-
97
  with open(file_path, 'w', encoding='utf-8') as f:
98
  json.dump(data_list, f, indent=2, ensure_ascii=False)
99
-
100
- # 验证文件是否成功写入
101
- if os.path.exists(file_path) and os.path.getsize(file_path) > 0:
102
- return True, f"Data saved successfully to '{os.path.basename(file_path)}'."
103
- else:
104
- return False, f"Failed to write data to '{os.path.basename(file_path)}'."
105
  except Exception as e:
106
  print(f"Error saving JSON to {file_path}: {e}")
107
  return False, f"Error saving data to '{os.path.basename(file_path)}': {e}"
@@ -116,108 +82,51 @@ def save_data(dataframe, selected_file):
116
  file_path = os.path.join(DATA_DIR, selected_file)
117
 
118
  try:
 
 
 
119
  data_list = dataframe.to_dict(orient='records')
120
-
 
121
  cleaned_data = []
122
  for item in data_list:
123
- cleaned_item = {k: v for k, v in item.items() if v is not None or k == 'Params'}
 
 
124
  cleaned_item.setdefault('Name', '')
125
  cleaned_item.setdefault('Title', '')
126
  cleaned_item.setdefault('Params', '')
127
  cleaned_data.append(cleaned_item)
128
 
129
- success, status = save_data_internal(cleaned_data, file_path)
130
-
131
- if IS_HF_SPACE and success:
132
- status += " (Note: Changes are temporary in HF Spaces and will be lost on restart)"
133
-
134
  return status
135
  except Exception as e:
136
  print(f"Error preparing data for saving to {selected_file}: {e}")
137
  return f"Error preparing data for saving to '{selected_file}': {e}"
138
 
139
- def create_new_file(filename):
140
- """创建新的 JSON 文件"""
141
- if not filename:
142
- return "Error: Please enter a filename."
143
-
144
- if not filename.endswith('.json'):
145
- filename += '.json'
146
-
147
- file_path = os.path.join(DATA_DIR, filename)
148
-
149
- if os.path.exists(file_path):
150
- return f"Error: File '{filename}' already exists."
151
-
152
- try:
153
- # 创建空的 JSON 文件
154
- with open(file_path, 'w', encoding='utf-8') as f:
155
- json.dump([], f)
156
-
157
- available_files = find_json_files(DATA_DIR)
158
- return f"File '{filename}' created successfully.", gr.Dropdown(choices=available_files, value=filename)
159
- except Exception as e:
160
- return f"Error creating file '{filename}': {e}", gr.Dropdown()
161
-
162
- def save_and_refresh(dataframe, selected_file):
163
- """保存数据并刷新文件列表"""
164
- save_status = save_data(dataframe, selected_file)
165
- available_files = find_json_files(DATA_DIR)
166
- return save_status, gr.Dropdown(choices=available_files, value=selected_file)
167
-
168
- def refresh_files_and_reload(selected_file):
169
- """刷新文件列表并重新加载当前选中的文件"""
170
- available_files = find_json_files(DATA_DIR)
171
- if selected_file and selected_file in available_files:
172
- df, status = load_data(selected_file)
173
- return gr.Dropdown(choices=available_files, value=selected_file), df, status
174
- else:
175
- df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
176
- status = "File list refreshed. Please select a file."
177
- return gr.Dropdown(choices=available_files), df, status
178
-
179
- # --- 初始化 ---
180
- # 在 HF Spaces 环境中创建示例文件
181
- if IS_HF_SPACE:
182
- create_sample_files()
183
 
184
  # Find available JSON files at startup
185
  available_files = find_json_files(DATA_DIR)
186
 
187
- # --- Gradio Interface Definition ---
188
-
189
  with gr.Blocks() as app:
190
- if IS_HF_SPACE:
191
- gr.Markdown("""
192
- # Multi-JSON Data Editor (HF Spaces Demo)
193
- ⚠️ **Note**: This is running on Hugging Face Spaces. Changes are temporary and will be lost when the space restarts.
194
- For persistent storage, download your files or use a local installation.
195
- """)
196
- else:
197
- gr.Markdown(f"""
198
- # Multi-JSON Data Editor
199
- Select a JSON file from the dropdown to load, view, edit, and save data.
200
- Files are scanned from the directory: `{os.path.abspath(DATA_DIR)}`
201
- """)
202
 
203
  # Status Textbox
204
  status_text = gr.Textbox(label="Status", interactive=False, value="Select a file to begin.")
205
 
206
- # File management section
207
- with gr.Row():
208
- with gr.Column(scale=3):
209
- file_selector = gr.Dropdown(
210
- choices=available_files,
211
- label="Select JSON File",
212
- info="Choose the JSON file you want to edit.",
213
- interactive=True
214
- )
215
- with gr.Column(scale=1):
216
- new_filename = gr.Textbox(
217
- label="New File Name",
218
- placeholder="Enter filename (without .json)",
219
- interactive=True
220
- )
221
 
222
  # DataFrame for Editing
223
  data_df = gr.DataFrame(
@@ -231,50 +140,34 @@ with gr.Blocks() as app:
231
 
232
  # Action Buttons
233
  with gr.Row():
234
- refresh_button = gr.Button("🔄 Refresh File List")
235
- load_button = gr.Button("📂 Reload Selected File")
236
- save_button = gr.Button("💾 Save Changes")
237
- create_button = gr.Button("📄 Create New File")
238
 
239
  # --- Event Handling ---
240
 
 
241
  file_selector.change(
242
  fn=load_data,
243
  inputs=file_selector,
244
  outputs=[data_df, status_text]
245
  )
246
 
247
- refresh_button.click(
248
- fn=refresh_files_and_reload,
249
- inputs=file_selector,
250
- outputs=[file_selector, data_df, status_text]
251
- )
252
-
253
  load_button.click(
254
  fn=load_data,
255
- inputs=file_selector,
256
  outputs=[data_df, status_text]
257
  )
258
-
259
  save_button.click(
260
- fn=save_and_refresh,
261
- inputs=[data_df, file_selector],
262
- outputs=[status_text, file_selector]
263
- )
264
-
265
- create_button.click(
266
- fn=create_new_file,
267
- inputs=new_filename,
268
- outputs=[status_text, file_selector]
269
  )
270
 
271
  # --- Launch the App ---
272
  if __name__ == "__main__":
273
- if not available_files and not IS_HF_SPACE:
274
  print(f"Warning: No .json files found in the directory '{os.path.abspath(DATA_DIR)}'.")
275
  print("Create some .json files in the directory and restart the application.")
276
-
277
- app.launch(
278
- share=False if IS_HF_SPACE else True,
279
- server_name="0.0.0.0" if IS_HF_SPACE else "127.0.0.1"
280
- )
 
2
  import pandas as pd
3
  import json
4
  import os
 
 
 
5
 
6
  # --- Configuration & Helpers ---
7
+ DATA_DIR = '.' # Directory to scan for JSON files (current directory)
 
 
 
 
 
 
 
 
 
8
 
9
  def find_json_files(directory):
10
  """Finds all .json files in the specified directory."""
 
14
  except FileNotFoundError:
15
  return []
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  # --- Data Processing Functions ---
18
 
19
  def load_data(selected_file):
20
  """Loads data from the selected JSON file into a Pandas DataFrame."""
21
  if not selected_file:
22
+ # No file selected, return empty DataFrame and instructions
23
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
24
  status = "Please select a JSON file from the dropdown to load."
25
  return df, status
 
27
  file_path = os.path.join(DATA_DIR, selected_file)
28
 
29
  if not os.path.exists(file_path):
30
+ # Should not happen if dropdown is populated correctly, but handle anyway
31
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
32
  status = f"Error: File '{selected_file}' not found in '{DATA_DIR}'."
33
  return df, status
34
  else:
35
  try:
36
+ # Handle empty file case
37
  if os.path.getsize(file_path) == 0:
38
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
39
  status = f"'{selected_file}' is empty. Displaying empty table. You can add rows and save."
40
  return df, status
41
 
42
+ # Try reading JSON
43
+ df = pd.read_json(file_path, orient='records', dtype=str) # Read all as string initially
44
+ # Ensure required columns exist, fill missing with empty strings
45
  df = df.reindex(columns=['Name', 'Title', 'Params'], fill_value='')
46
+ # Fill any remaining NaN/None values just in case
47
  df = df.fillna('')
48
  status = f"Data loaded successfully from '{selected_file}'."
49
+ except ValueError as e: # Handles JSON decoding errors or incorrect format
50
  print(f"Error loading JSON from {selected_file}: {e}")
51
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
52
  status = f"Error loading '{selected_file}': Invalid JSON format or structure ({e}). Displaying empty table."
 
55
  df = pd.DataFrame(columns=['Name', 'Title', 'Params'])
56
  status = f"Unexpected error loading '{selected_file}': {e}. Displaying empty table."
57
 
58
+ # Ensure consistent string type for display
59
  df['Name'] = df['Name'].astype(str)
60
  df['Title'] = df['Title'].astype(str)
61
  df['Params'] = df['Params'].astype(str)
 
65
  def save_data_internal(data_list, file_path):
66
  """Writes a Python list to a specific JSON file path."""
67
  try:
 
 
 
68
  with open(file_path, 'w', encoding='utf-8') as f:
69
  json.dump(data_list, f, indent=2, ensure_ascii=False)
70
+ return True, f"Data saved successfully to '{os.path.basename(file_path)}'."
 
 
 
 
 
71
  except Exception as e:
72
  print(f"Error saving JSON to {file_path}: {e}")
73
  return False, f"Error saving data to '{os.path.basename(file_path)}': {e}"
 
82
  file_path = os.path.join(DATA_DIR, selected_file)
83
 
84
  try:
85
+ # Convert DataFrame to list of dictionaries
86
+ # Replace empty strings potentially introduced by editing back to None for cleaner JSON
87
+ # but keep actual 'Params' JSON strings even if empty {}
88
  data_list = dataframe.to_dict(orient='records')
89
+
90
+ # Clean data: Remove None values, ensure required keys exist
91
  cleaned_data = []
92
  for item in data_list:
93
+ # Only keep key if value is not None, unless it's 'Params' which can be an empty string '{}' etc.
94
+ cleaned_item = {k: v for k, v in item.items() if v is not None or k == 'Params'} # Keep params even if empty string
95
+ # Ensure standard keys exist, defaulting to empty string if missing after None removal
96
  cleaned_item.setdefault('Name', '')
97
  cleaned_item.setdefault('Title', '')
98
  cleaned_item.setdefault('Params', '')
99
  cleaned_data.append(cleaned_item)
100
 
101
+
102
+ _, status = save_data_internal(cleaned_data, file_path)
 
 
 
103
  return status
104
  except Exception as e:
105
  print(f"Error preparing data for saving to {selected_file}: {e}")
106
  return f"Error preparing data for saving to '{selected_file}': {e}"
107
 
108
+ # --- Gradio Interface Definition ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  # Find available JSON files at startup
111
  available_files = find_json_files(DATA_DIR)
112
 
 
 
113
  with gr.Blocks() as app:
114
+ gr.Markdown(f"""
115
+ # Multi-JSON Data Editor
116
+ Select a JSON file from the dropdown to load, view, edit, and save data.
117
+ Files are scanned from the directory: `{os.path.abspath(DATA_DIR)}`
118
+ """)
 
 
 
 
 
 
 
119
 
120
  # Status Textbox
121
  status_text = gr.Textbox(label="Status", interactive=False, value="Select a file to begin.")
122
 
123
+ # File Selector Dropdown
124
+ file_selector = gr.Dropdown(
125
+ choices=available_files,
126
+ label="Select JSON File",
127
+ info="Choose the JSON file you want to edit.",
128
+ interactive=True
129
+ )
 
 
 
 
 
 
 
 
130
 
131
  # DataFrame for Editing
132
  data_df = gr.DataFrame(
 
140
 
141
  # Action Buttons
142
  with gr.Row():
143
+ # Load button might be redundant if dropdown change triggers load, but can be useful for refresh
144
+ load_button = gr.Button("🔄 Reload Selected File")
145
+ save_button = gr.Button("💾 Save Changes to Selected File")
 
146
 
147
  # --- Event Handling ---
148
 
149
+ # When the dropdown selection changes, load the corresponding file
150
  file_selector.change(
151
  fn=load_data,
152
  inputs=file_selector,
153
  outputs=[data_df, status_text]
154
  )
155
 
156
+ # Button click events - they use the currently selected file from the dropdown
 
 
 
 
 
157
  load_button.click(
158
  fn=load_data,
159
+ inputs=file_selector, # Pass the current dropdown value
160
  outputs=[data_df, status_text]
161
  )
 
162
  save_button.click(
163
+ fn=save_data,
164
+ inputs=[data_df, file_selector], # Pass current DataFrame AND current dropdown value
165
+ outputs=status_text
 
 
 
 
 
 
166
  )
167
 
168
  # --- Launch the App ---
169
  if __name__ == "__main__":
170
+ if not available_files:
171
  print(f"Warning: No .json files found in the directory '{os.path.abspath(DATA_DIR)}'.")
172
  print("Create some .json files in the directory and restart the application.")
173
+ app.launch()