QIDNLF commited on
Commit
cf417b8
ยท
verified ยท
1 Parent(s): ad46fca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -115
app.py CHANGED
@@ -5,21 +5,23 @@ import os
5
  import re
6
  import base64
7
 
8
- # 1๏ธโƒฃ ์ €์žฅ์†Œ ๋ฐ ํ™˜๊ฒฝ ์„ค์ •
9
  UPLOAD_DIR = "uploaded_dbs"
10
  if not os.path.exists(UPLOAD_DIR):
11
  os.makedirs(UPLOAD_DIR)
12
 
13
  db_registry = []
14
 
15
- # BLOB(์ด๋ฏธ์ง€) ๋ฐ์ดํ„ฐ๋ฅผ HTML ํƒœ๊ทธ๋กœ ๋ณ€ํ™˜
 
 
16
  def blob_to_base64_html(blob_data):
17
  if blob_data is None or pd.isna(blob_data):
18
  return ""
19
  try:
20
  if isinstance(blob_data, (bytes, bytearray)):
21
  encoded_string = base64.b64encode(blob_data).decode('utf-8')
22
- return f'<img src="data:image/png;base64,{encoded_string}" width="200" height="auto" />'
23
  return str(blob_data)
24
  except:
25
  return str(blob_data)
@@ -32,8 +34,8 @@ def natural_sort_key(s):
32
  def refresh_registry_data():
33
  global db_registry
34
  db_registry = []
35
- if not os.path.exists(UPLOAD_DIR): return []
36
  db_files = [f for f in os.listdir(UPLOAD_DIR) if f.endswith(".db")]
 
37
  for filename in db_files:
38
  name_only = filename.replace(".db", "")
39
  parts = name_only.split("_")
@@ -43,149 +45,128 @@ def refresh_registry_data():
43
  "standard": parts[0],
44
  "version": parts[1]
45
  })
 
46
  return sorted(list(set([db["standard"] for db in db_registry])))
47
 
48
- # 2๏ธโƒฃ UI ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜
 
 
49
  def on_load():
50
  standards = refresh_registry_data()
51
- return gr.Dropdown(choices=standards, value=None)
52
 
53
  def update_version_dd(standard):
54
- if not standard: return gr.Dropdown(choices=[], value=None)
55
- versions = sorted(list(set([db["version"] for db in db_registry if db["standard"] == standard])))
56
- return gr.Dropdown(choices=versions, value=None)
 
 
 
57
 
58
  def update_category_dd(standard, version):
59
- if not standard or not version: return gr.Dropdown(choices=[], value=None)
 
 
60
  choices = ["ALL"]
 
61
  try:
62
  target_db = next(db for db in db_registry if db["standard"] == standard and db["version"] == version)
63
  conn = sqlite3.connect(target_db["path"])
64
- all_tables = pd.read_sql("SELECT name FROM sqlite_master WHERE type='table';", conn)['name'].tolist()
65
-
66
  main_t = f"{standard}_{version}"
67
- if main_t not in all_tables:
68
- candidates = [t for t in all_tables if standard.lower() in t.lower() and version.lower() in t.lower()]
69
- main_t = candidates[0] if candidates else all_tables[0]
70
-
71
  cols_info = pd.read_sql(f"PRAGMA table_info([{main_t}])", conn)
72
- orig_cols = cols_info['name'].tolist()
73
- lower_cols = [c.strip().lower() for c in orig_cols]
74
-
75
- # ๐Ÿ’ก ์žฅ(chapter) + ์นดํ…Œ๊ณ ๋ฆฌ(category) ๊ฒฐํ•ฉ ๋กœ์ง
76
  if 'chapter' in lower_cols and 'category' in lower_cols:
77
- real_ch = orig_cols[lower_cols.index('chapter')]
78
- real_cat = orig_cols[lower_cols.index('category')]
79
-
80
- # DISTINCT๋กœ ์ค‘๋ณต ์ œ๊ฑฐ๋œ ์žฅ.์นดํ…Œ๊ณ ๋ฆฌ ์Œ์„ ๊ฐ€์ ธ์˜ด
81
- df_cat = pd.read_sql(f"SELECT DISTINCT [{real_ch}], [{real_cat}] FROM [{main_t}]", conn)
82
-
83
- cats = []
84
- for _, row in df_cat.iterrows():
85
- ch = str(row[real_ch]).strip() if row[real_ch] is not None else ""
86
- ca = str(row[real_cat]).strip() if row[real_cat] is not None else ""
87
- if ch:
88
- # '1.Scope' ํ˜•์‹์œผ๋กœ ์ƒ์„ฑ
89
- cats.append(f"{ch}.{ca}" if ca else ch)
90
-
91
- cats.sort(key=natural_sort_key)
92
- choices.extend(cats)
93
-
94
- # ๋ถ€์† ํ…Œ์ด๋ธ” ์ถ”๊ฐ€
95
- prefix = f"{standard}_{version}_"
96
- for t in all_tables:
97
- if t != main_t:
98
- choices.append(t.replace(prefix, ""))
99
-
100
  conn.close()
101
  except:
102
  pass
103
- return gr.Dropdown(choices=choices, value=None)
104
 
105
- # 3๏ธ๏ฟฝ๏ฟฝ๏ฟฝ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๋กœ์ง (DB ์ˆœ์„œ ์œ ์ง€)
 
 
 
 
106
  def display_data(standard, version, selection):
107
- if not all([standard, version, selection]): return None
108
- try:
109
- target_db = next(db for db in db_registry if db["standard"] == standard and db["version"] == version)
110
- conn = sqlite3.connect(target_db["path"])
111
- all_tables = pd.read_sql("SELECT name FROM sqlite_master WHERE type='table';", conn)['name'].tolist()
112
-
113
- main_t = f"{standard}_{version}"
114
- if main_t not in all_tables:
115
- candidates = [t for t in all_tables if standard.lower() in t.lower() and version.lower() in t.lower()]
116
- main_t = candidates[0] if candidates else all_tables[0]
117
-
118
- is_sub_table = False
119
- if selection == "ALL":
120
- df = pd.read_sql(f"SELECT * FROM [{main_t}] ORDER BY rowid", conn)
121
- elif "." in selection:
122
- # '1.Scope'์—์„œ ์žฅ๊ณผ ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฆฌ
123
- ch, ca = selection.split('.', 1)
124
- cols_info = pd.read_sql(f"PRAGMA table_info([{main_t}])", conn)
125
- cols_lower = [c.strip().lower() for c in cols_info['name'].tolist()]
126
- real_ch = cols_info['name'].tolist()[cols_lower.index('chapter')]
127
- real_cat = cols_info['name'].tolist()[cols_lower.index('category')]
128
-
129
- df = pd.read_sql(f"SELECT * FROM [{main_t}] WHERE CAST([{real_ch}] AS TEXT)=? AND CAST([{real_cat}] AS TEXT)=? ORDER BY rowid",
130
- conn, params=[ch, ca])
131
- else:
132
- is_sub_table = True
133
- actual_table = next((t for t in all_tables if selection in t), selection)
134
- df = pd.read_sql(f"SELECT * FROM [{actual_table}] ORDER BY rowid", conn)
135
- conn.close()
136
 
137
- if not df.empty:
138
- # ์ด๋ฏธ์ง€ ๋ณ€ํ™˜
139
- for col in df.columns:
140
- df[col] = df[col].apply(blob_to_base64_html)
141
-
142
- # ๋ณธ๋ฌธ ์กฐํšŒ ์‹œ ์—ด ํ•„ํ„ฐ๋ง (DB ์ˆœ์„œ ์œ ์ง€)
143
- if not is_sub_table:
144
- base_cols = [c for c in ['section', 'description'] if c in df.columns]
145
- # ์ด๋ฏธ์ง€๊ฐ€ ํฌํ•จ๋œ ์—ด ์ž๋™ ์ถ”๊ฐ€
146
- image_cols = [c for c in df.columns if c not in base_cols and df[c].astype(str).str.contains('<img', na=False).any()]
147
- df = df[base_cols + image_cols]
148
-
149
- return df
150
- except Exception as e:
151
- return pd.DataFrame({"Error": [f"์กฐํšŒ ์‹คํŒจ: {str(e)}"]})
152
-
153
- # 4๏ธโƒฃ UI ๊ตฌ์„ฑ
154
  def unified_search(bs, bv, bc, cs, cv, cc):
155
 
 
156
  if bs and bv and bc and not (cs and cv and cc):
157
  return display_data(bs, bv, bc)
158
 
 
159
  if bs and bv and bc and cs and cv and cc:
160
  df_base = display_data(bs, bv, bc)
161
  df_comp = display_data(cs, cv, cc)
162
 
163
- try:
164
- merged = pd.merge(
165
- df_base,
166
- df_comp,
167
- on="section",
168
- how="outer",
169
- suffixes=("_base", "_comp")
170
- )
171
- return merged
172
- except Exception as e:
173
- return pd.DataFrame({"Error": [str(e)]})
174
 
175
  return pd.DataFrame({"Info": ["์„ ํƒ์„ ์™„๋ฃŒํ•˜์„ธ์š”"]})
176
-
177
- with gr.Blocks(css="""
178
- table td {
179
- white-space: normal !important;
180
- word-break: break-word !important;
181
- }
182
- """) as demo:
183
 
184
  gr.Markdown("# ๐Ÿ“œ Regulation Viewer")
185
 
186
  with gr.Row():
187
 
188
- # ๐Ÿ‘‰ ์™ผ์ชฝ
189
  with gr.Column(scale=1):
190
 
191
  with gr.Group():
@@ -200,11 +181,10 @@ table td {
200
  comp_version = gr.Dropdown(label="Version")
201
  comp_category = gr.Dropdown(label="Category")
202
 
203
- # ๐Ÿ‘‰ ๏ฟฝ๏ฟฝ๋ฅธ์ชฝ
204
  with gr.Column(scale=4):
205
  gr.Markdown("### ๐Ÿ“Š ๋‚ด์šฉ")
206
 
207
- # โ— height ์ œ๊ฑฐ
208
  output_df = gr.Dataframe(
209
  wrap=True,
210
  interactive=False,
@@ -215,7 +195,7 @@ table td {
215
  with gr.Row():
216
  search_btn = gr.Button("๐Ÿ” ์กฐํšŒ")
217
 
218
- # ๊ธฐ์กด ์ด๋ฒคํŠธ ๊ทธ๋Œ€๋กœ
219
  demo.load(on_load, None, base_standard)
220
  demo.load(on_load, None, comp_standard)
221
 
@@ -232,6 +212,17 @@ table td {
232
  output_df
233
  )
234
 
235
- # โ— theme๋Š” ์—ฌ๊ธฐ๋กœ ์ด๋™
 
 
236
  if __name__ == "__main__":
237
- demo.launch(theme=gr.themes.Soft())
 
 
 
 
 
 
 
 
 
 
5
  import re
6
  import base64
7
 
8
+ # 1๏ธโƒฃ ์ €์žฅ์†Œ ์„ค์ •
9
  UPLOAD_DIR = "uploaded_dbs"
10
  if not os.path.exists(UPLOAD_DIR):
11
  os.makedirs(UPLOAD_DIR)
12
 
13
  db_registry = []
14
 
15
+ # --------------------------
16
+ # ์œ ํ‹ธ ํ•จ์ˆ˜ (๊ทธ๋Œ€๋กœ ์œ ์ง€)
17
+ # --------------------------
18
  def blob_to_base64_html(blob_data):
19
  if blob_data is None or pd.isna(blob_data):
20
  return ""
21
  try:
22
  if isinstance(blob_data, (bytes, bytearray)):
23
  encoded_string = base64.b64encode(blob_data).decode('utf-8')
24
+ return f'<img src="data:image/png;base64,{encoded_string}" width="200" />'
25
  return str(blob_data)
26
  except:
27
  return str(blob_data)
 
34
  def refresh_registry_data():
35
  global db_registry
36
  db_registry = []
 
37
  db_files = [f for f in os.listdir(UPLOAD_DIR) if f.endswith(".db")]
38
+
39
  for filename in db_files:
40
  name_only = filename.replace(".db", "")
41
  parts = name_only.split("_")
 
45
  "standard": parts[0],
46
  "version": parts[1]
47
  })
48
+
49
  return sorted(list(set([db["standard"] for db in db_registry])))
50
 
51
+ # --------------------------
52
+ # ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ
53
+ # --------------------------
54
  def on_load():
55
  standards = refresh_registry_data()
56
+ return gr.Dropdown(choices=standards)
57
 
58
  def update_version_dd(standard):
59
+ if not standard:
60
+ return gr.Dropdown(choices=[])
61
+ versions = sorted(list(set([
62
+ db["version"] for db in db_registry if db["standard"] == standard
63
+ ])))
64
+ return gr.Dropdown(choices=versions)
65
 
66
  def update_category_dd(standard, version):
67
+ if not standard or not version:
68
+ return gr.Dropdown(choices=[])
69
+
70
  choices = ["ALL"]
71
+
72
  try:
73
  target_db = next(db for db in db_registry if db["standard"] == standard and db["version"] == version)
74
  conn = sqlite3.connect(target_db["path"])
75
+
76
+ tables = pd.read_sql("SELECT name FROM sqlite_master WHERE type='table';", conn)['name'].tolist()
77
  main_t = f"{standard}_{version}"
78
+
79
+ if main_t not in tables:
80
+ main_t = tables[0]
81
+
82
  cols_info = pd.read_sql(f"PRAGMA table_info([{main_t}])", conn)
83
+ cols = cols_info['name'].tolist()
84
+ lower_cols = [c.lower() for c in cols]
85
+
 
86
  if 'chapter' in lower_cols and 'category' in lower_cols:
87
+ ch = cols[lower_cols.index('chapter')]
88
+ ca = cols[lower_cols.index('category')]
89
+
90
+ df = pd.read_sql(f"SELECT DISTINCT [{ch}], [{ca}] FROM [{main_t}]", conn)
91
+
92
+ for _, row in df.iterrows():
93
+ c = str(row[ch])
94
+ cat = str(row[ca])
95
+ choices.append(f"{c}.{cat}")
96
+
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  conn.close()
98
  except:
99
  pass
 
100
 
101
+ return gr.Dropdown(choices=choices)
102
+
103
+ # --------------------------
104
+ # ๋ฐ์ดํ„ฐ ์กฐํšŒ
105
+ # --------------------------
106
  def display_data(standard, version, selection):
107
+ if not all([standard, version, selection]):
108
+ return None
109
+
110
+ target_db = next(db for db in db_registry if db["standard"] == standard and db["version"] == version)
111
+ conn = sqlite3.connect(target_db["path"])
112
+
113
+ main_t = f"{standard}_{version}"
114
+
115
+ if selection == "ALL":
116
+ df = pd.read_sql(f"SELECT * FROM [{main_t}]", conn)
117
+ elif "." in selection:
118
+ ch, ca = selection.split(".", 1)
119
+ df = pd.read_sql(f"SELECT * FROM [{main_t}] WHERE chapter=? AND category=?", conn, params=[ch, ca])
120
+ else:
121
+ df = pd.read_sql(f"SELECT * FROM [{selection}]", conn)
122
+
123
+ conn.close()
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
+ if not df.empty:
126
+ for col in df.columns:
127
+ df[col] = df[col].apply(blob_to_base64_html)
128
+
129
+ if 'section' in df.columns and 'description' in df.columns:
130
+ df = df[['section', 'description']]
131
+
132
+ return df
133
+
134
+ # --------------------------
135
+ # ๐Ÿ”ฅ ํ†ตํ•ฉ ์กฐํšŒ (ํ•ต์‹ฌ)
136
+ # --------------------------
 
 
 
 
 
137
  def unified_search(bs, bv, bc, cs, cv, cc):
138
 
139
+ # ๊ธฐ์ค€๋งŒ
140
  if bs and bv and bc and not (cs and cv and cc):
141
  return display_data(bs, bv, bc)
142
 
143
+ # ๋น„๊ต
144
  if bs and bv and bc and cs and cv and cc:
145
  df_base = display_data(bs, bv, bc)
146
  df_comp = display_data(cs, cv, cc)
147
 
148
+ merged = pd.merge(
149
+ df_base,
150
+ df_comp,
151
+ on="section",
152
+ how="outer",
153
+ suffixes=("_base", "_comp")
154
+ )
155
+
156
+ return merged
 
 
157
 
158
  return pd.DataFrame({"Info": ["์„ ํƒ์„ ์™„๋ฃŒํ•˜์„ธ์š”"]})
159
+
160
+ # --------------------------
161
+ # UI ๊ตฌ์„ฑ
162
+ # --------------------------
163
+ with gr.Blocks() as demo:
 
 
164
 
165
  gr.Markdown("# ๐Ÿ“œ Regulation Viewer")
166
 
167
  with gr.Row():
168
 
169
+ # ์™ผ์ชฝ
170
  with gr.Column(scale=1):
171
 
172
  with gr.Group():
 
181
  comp_version = gr.Dropdown(label="Version")
182
  comp_category = gr.Dropdown(label="Category")
183
 
184
+ # ์˜ค๋ฅธ์ชฝ
185
  with gr.Column(scale=4):
186
  gr.Markdown("### ๐Ÿ“Š ๋‚ด์šฉ")
187
 
 
188
  output_df = gr.Dataframe(
189
  wrap=True,
190
  interactive=False,
 
195
  with gr.Row():
196
  search_btn = gr.Button("๐Ÿ” ์กฐํšŒ")
197
 
198
+ # ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
199
  demo.load(on_load, None, base_standard)
200
  demo.load(on_load, None, comp_standard)
201
 
 
212
  output_df
213
  )
214
 
215
+ # --------------------------
216
+ # ์‹คํ–‰
217
+ # --------------------------
218
  if __name__ == "__main__":
219
+ demo.launch(
220
+ theme=gr.themes.Soft(),
221
+ share=True,
222
+ css="""
223
+ table td {
224
+ white-space: normal !important;
225
+ word-break: break-word !important;
226
+ }
227
+ """
228
+ )