MTeguri commited on
Commit
005983f
·
1 Parent(s): 84a4d04

Refactor data import functionality to support tab-separated input and improve Supabase integration

Browse files

- Updated `import_data_to_supabase` to accept tab-separated text input instead of CSV files.
- Enhanced table creation logic to handle DataFrame directly and improved error handling.
- Modified Gradio interface to reflect changes in input method and updated labels for clarity.
- Cleaned up code comments and improved function documentation for better understanding.

Files changed (1) hide show
  1. app.py +50 -41
app.py CHANGED
@@ -7,17 +7,20 @@ SUPABASE_URL = os.environ.get('SUPABASE_URL')
7
 
8
  SUPABASE_KEY = os.environ.get('SUPABASE_KEY')
9
 
10
- import gradio as gr
11
- import pandas as pd
 
 
 
12
  import math
 
13
 
14
- # Supabaseクライアントは事前に初期化しておく必要があります
15
- # from supabase import create_client
16
- # supabase_client = create_client(SUPABASE_URL, SUPABASE_KEY)
17
 
18
 
19
  def pandas_dtype_to_supabase_type(dtype):
20
- """Maps pandas data types to Supabase SQL data types."""
21
  if pd.api.types.is_integer_dtype(dtype):
22
  return "integer"
23
  elif pd.api.types.is_float_dtype(dtype):
@@ -30,12 +33,13 @@ def pandas_dtype_to_supabase_type(dtype):
30
  return "text"
31
 
32
 
33
- def create_table_if_not_exists(db_name, dataframe):
34
  """
35
- Creates a table in Supabase if it doesn't exist, using RPC `exec_sql`.
 
36
  """
37
  columns = []
38
- for col_name, dtype in dataframe.dtypes.items():
39
  supabase_type = pandas_dtype_to_supabase_type(dtype)
40
  columns.append(f'"{col_name}" {supabase_type}')
41
 
@@ -46,11 +50,9 @@ def create_table_if_not_exists(db_name, dataframe):
46
  {columns_sql}
47
  );
48
  """
49
- print(f"Executing SQL for table creation:\n{create_table_sql}")
50
 
51
  try:
52
  response = supabase_client.rpc("exec_sql", {"sql": create_table_sql}).execute()
53
-
54
  resp_data = getattr(response, "data", None)
55
  resp_error = getattr(response, "error", None)
56
 
@@ -63,15 +65,11 @@ def create_table_if_not_exists(db_name, dataframe):
63
  return True, f"Table '{db_name}' created or already exists. (no data returned)"
64
 
65
  except Exception as e:
66
- print(f"Exception during table creation RPC call: {e}")
67
  return False, f"Exception during table creation: {e}"
68
 
69
 
70
  def clean_dataframe_for_json(df: pd.DataFrame):
71
- """
72
- Convert DataFrame to JSON-compliant list of dicts
73
- (replace NaN, NaT, inf, -inf with None).
74
- """
75
  records = df.to_dict(orient="records")
76
  cleaned = []
77
  for row in records:
@@ -87,36 +85,42 @@ def clean_dataframe_for_json(df: pd.DataFrame):
87
  return cleaned
88
 
89
 
90
- def import_data_to_supabase(csv_file, db_name):
91
  """
92
- Imports data from a CSV file to a Supabase table,
93
- creating the table if it doesn't exist.
94
  """
95
- global supabase_client
96
  full_message = []
97
 
98
- if not csv_file or not db_name:
99
- return "Please upload a CSV file and provide a table name."
 
 
100
 
101
  try:
102
- # 1. CSV読込
103
- df = pd.read_csv(csv_file.name)
104
-
105
- # 2. テーブル作成
106
- table_creation_success, table_creation_msg = create_table_if_not_exists(db_name, df)
107
- full_message.append(f"Table Creation Status: {table_creation_msg}")
 
 
 
 
 
 
 
 
108
 
109
- # 3. JSON対応にクリーニング(NaN, NaT, inf → None)
110
  data = clean_dataframe_for_json(df)
111
-
112
  if not data:
113
- full_message.append("Data Insertion Status: CSV file empty or not parsed. No data inserted.")
114
  return "\n".join(full_message)
115
 
116
- # 4. データ挿入
117
- print(f"Attempting to insert {len(data)} rows into table '{db_name}'.")
118
- response = supabase_client.table(db_name).insert(data).execute()
119
-
120
  resp_data = getattr(response, "data", None)
121
  resp_error = getattr(response, "error", None)
122
 
@@ -124,7 +128,7 @@ def import_data_to_supabase(csv_file, db_name):
124
  full_message.append(
125
  f"Data Insertion Status: Error inserting data - {getattr(resp_error, 'message', str(resp_error))}"
126
  )
127
- elif resp_data:
128
  full_message.append(f"Data Insertion Status: Successfully inserted {len(resp_data)} rows.")
129
  else:
130
  full_message.append("Data Insertion Status: Insert executed, but no data returned.")
@@ -139,12 +143,17 @@ def import_data_to_supabase(csv_file, db_name):
139
  iface = gr.Interface(
140
  fn=import_data_to_supabase,
141
  inputs=[
142
- gr.File(label="Upload CSV File"),
143
- gr.Textbox(label="Supabase Database Table Name")
 
 
 
 
144
  ],
145
  outputs="text",
146
- title="Supabase Data Importer",
147
- description="CSVファイルをアップロードし、データをSupabaseデータベースのテーブルにインポートします。指定されたテーブルが存在しない場合は新しく作成します。"
148
  )
149
 
150
- iface.launch(mcp_server=True)
 
 
7
 
8
  SUPABASE_KEY = os.environ.get('SUPABASE_KEY')
9
 
10
+ import supabase
11
+
12
+ # クライアントの初期化
13
+ supabase_client = supabase.create_client(SUPABASE_URL, SUPABASE_KEY)
14
+
15
  import math
16
+ from io import StringIO
17
 
18
+ import gradio as gr
19
+ import pandas as pd
 
20
 
21
 
22
  def pandas_dtype_to_supabase_type(dtype):
23
+ """Maps pandas dtypes to Supabase(PostgreSQL) types."""
24
  if pd.api.types.is_integer_dtype(dtype):
25
  return "integer"
26
  elif pd.api.types.is_float_dtype(dtype):
 
33
  return "text"
34
 
35
 
36
+ def create_table_if_not_exists(db_name: str, df: pd.DataFrame):
37
  """
38
+ Supabase 上にテーブルが無ければ作成します。
39
+ 'exec_sql(sql text)' という RPC を作成してある前提です。
40
  """
41
  columns = []
42
+ for col_name, dtype in df.dtypes.items():
43
  supabase_type = pandas_dtype_to_supabase_type(dtype)
44
  columns.append(f'"{col_name}" {supabase_type}')
45
 
 
50
  {columns_sql}
51
  );
52
  """
 
53
 
54
  try:
55
  response = supabase_client.rpc("exec_sql", {"sql": create_table_sql}).execute()
 
56
  resp_data = getattr(response, "data", None)
57
  resp_error = getattr(response, "error", None)
58
 
 
65
  return True, f"Table '{db_name}' created or already exists. (no data returned)"
66
 
67
  except Exception as e:
 
68
  return False, f"Exception during table creation: {e}"
69
 
70
 
71
  def clean_dataframe_for_json(df: pd.DataFrame):
72
+ """DataFrame → JSON互換の list[dict] に変換"""
 
 
 
73
  records = df.to_dict(orient="records")
74
  cleaned = []
75
  for row in records:
 
85
  return cleaned
86
 
87
 
88
+ def import_data_to_supabase(text_input: str, db_name: str):
89
  """
90
+ タブ区切りの貼り付けテキストを DataFrame に変換し、
91
+ Supabase のテーブルへ挿入する。
92
  """
 
93
  full_message = []
94
 
95
+ if not (text_input and text_input.strip()):
96
+ return "Please paste tab-separated data."
97
+ if not (db_name and db_name.strip()):
98
+ return "Please provide a table name."
99
 
100
  try:
101
+ # 1) タブ区切り読み込み、'null' を欠損値扱い
102
+ df = pd.read_csv(
103
+ StringIO(text_input),
104
+ sep="\t",
105
+ na_values=["null", "NULL", "NaN", ""],
106
+ keep_default_na=True,
107
+ )
108
+
109
+ # 2) テーブル作成
110
+ ok, msg = create_table_if_not_exists(db_name.strip(), df)
111
+ full_message.append(f"Table Creation Status: {msg}")
112
+
113
+ if not ok:
114
+ return "\n".join(full_message)
115
 
116
+ # 3) JSON 互換にクリーニング
117
  data = clean_dataframe_for_json(df)
 
118
  if not data:
119
+ full_message.append("Data Insertion Status: Input text empty or not parsed. No data inserted.")
120
  return "\n".join(full_message)
121
 
122
+ # 4) データ挿入
123
+ response = supabase_client.table(db_name.strip()).insert(data).execute()
 
 
124
  resp_data = getattr(response, "data", None)
125
  resp_error = getattr(response, "error", None)
126
 
 
128
  full_message.append(
129
  f"Data Insertion Status: Error inserting data - {getattr(resp_error, 'message', str(resp_error))}"
130
  )
131
+ elif resp_data is not None:
132
  full_message.append(f"Data Insertion Status: Successfully inserted {len(resp_data)} rows.")
133
  else:
134
  full_message.append("Data Insertion Status: Insert executed, but no data returned.")
 
143
  iface = gr.Interface(
144
  fn=import_data_to_supabase,
145
  inputs=[
146
+ gr.Textbox(
147
+ label="貼り付けデータ(タブ区切り)",
148
+ lines=12,
149
+ placeholder="項目名\t下限\t上限\n曝気空気量(微小動物槽-1)\t11.3\t16.5\n…"
150
+ ),
151
+ gr.Textbox(label="Supabase テーブル名(例: thresholds)"),
152
  ],
153
  outputs="text",
154
+ title="Supabase Data Importer (Paste TSV)",
155
+ description="Excel からコピーしたタブ区切りデータを貼り付け、Supabase に保存します。",
156
  )
157
 
158
+ if __name__ == "__main__":
159
+ iface.launch()