MTeguri's picture
Update Gradio interface launch to enable multi-client support
dbceedc
from dotenv import load_dotenv
load_dotenv()
import os
# 環境変数から取得
SUPABASE_URL = os.environ.get('SUPABASE_URL')
SUPABASE_KEY = os.environ.get('SUPABASE_KEY')
import supabase
# クライアントの初期化
supabase_client = supabase.create_client(SUPABASE_URL, SUPABASE_KEY)
import gradio as gr
import pandas as pd
import math
import time
from io import StringIO
import supabase
# =============================
# 型変換ヘルパー
# =============================
def pandas_dtype_to_supabase_type(dtype):
"""Maps pandas data types to Supabase SQL data types."""
if pd.api.types.is_integer_dtype(dtype):
return "integer"
elif pd.api.types.is_float_dtype(dtype):
return "double precision"
elif pd.api.types.is_bool_dtype(dtype):
return "boolean"
elif pd.api.types.is_datetime64_any_dtype(dtype):
return "timestamp with time zone"
else:
return "text"
# =============================
# テーブル作成関数
# =============================
def create_table_if_not_exists(db_name, dataframe):
"""
Creates a table in Supabase if it doesn't exist, using RPC `exec_sql`.
"""
columns = []
for col_name, dtype in dataframe.dtypes.items():
supabase_type = pandas_dtype_to_supabase_type(dtype)
columns.append(f'"{col_name}" {supabase_type}')
columns_sql = ", ".join(columns)
create_table_sql = f"""
CREATE TABLE IF NOT EXISTS public."{db_name}" (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
{columns_sql}
);
"""
print(f"Executing SQL for table creation:\n{create_table_sql}")
try:
response = supabase_client.rpc("exec_sql", {"sql": create_table_sql}).execute()
resp_data = getattr(response, "data", None)
resp_error = getattr(response, "error", None)
if resp_error:
return False, f"Error creating table: {getattr(resp_error, 'message', str(resp_error))}"
if resp_data:
return True, f"Table '{db_name}' created or already exists. RPC returned data: {resp_data}"
else:
return True, f"Table '{db_name}' created or already exists. (no data returned)"
except Exception as e:
print(f"Exception during table creation RPC call: {e}")
return False, f"Exception during table creation: {e}"
# =============================
# DataFrame の JSON 変換ヘルパー
# =============================
def clean_dataframe_for_json(df: pd.DataFrame):
"""
Convert DataFrame to JSON-compliant list of dicts
(replace NaN, NaT, inf, -inf with None).
"""
records = df.to_dict(orient="records")
cleaned = []
for row in records:
new_row = {}
for k, v in row.items():
if v is None:
new_row[k] = None
elif isinstance(v, float) and (math.isnan(v) or math.isinf(v)):
new_row[k] = None
else:
new_row[k] = v
cleaned.append(new_row)
return cleaned
# =============================
# メイン処理関数
# =============================
def import_data_to_supabase(text_input: str, db_name: str):
db_name = db_name.strip().lower() # 小文字に統一
full_message = []
try:
# 1. DataFrame 読み込み(タブ区切り & null対応)
df = pd.read_csv(
StringIO(text_input),
sep="\t",
na_values=["null", "NULL", "NaN", ""],
keep_default_na=True
)
# 2. テーブル作成
table_creation_success, table_creation_msg = create_table_if_not_exists(db_name, df)
full_message.append(f"Table Creation Status: {table_creation_msg}")
if not table_creation_success:
return "\n".join(full_message)
# 3. 数秒待機(スキーマキャッシュ反映待ち)
time.sleep(3)
# 4. JSON対応にクリーニング(NaN, NaT, inf → None)
data = clean_dataframe_for_json(df)
if not data:
full_message.append("Data Insertion Status: No data to insert.")
return "\n".join(full_message)
# 5. データ挿入
print(f"Attempting to insert {len(data)} rows into table '{db_name}'.")
response = supabase_client.table(db_name).insert(data).execute()
if getattr(response, "error", None):
full_message.append(
f"Data Insertion Status: Error inserting data - {response.error}"
)
elif getattr(response, "data", None):
full_message.append(
f"Data Insertion Status: Successfully inserted {len(response.data)} rows."
)
else:
full_message.append("Data Insertion Status: Insert executed, but no data returned.")
except Exception as e:
full_message.append(f"An unexpected error occurred during processing: {e}")
return "\n".join(full_message)
# =============================
# Gradio アプリ
# =============================
iface = gr.Interface(
fn=import_data_to_supabase,
inputs=[
gr.Textbox(label="Paste TSV Data Here", lines=15, placeholder="ここにタブ区切りデータを貼り付け"),
gr.Textbox(label="Supabase Database Table Name")
],
outputs="text",
title="Supabase Data Importer",
description="タブ区切りデータを貼り付け、Supabase データベースのテーブルにインポートします。テーブルが存在しない場合は新しく作成します。"
)
iface.launch(mcp_server=True)