Linker1907 commited on
Commit
445a7b6
·
1 Parent(s): a22d77d
Files changed (1) hide show
  1. app.py +28 -29
app.py CHANGED
@@ -20,7 +20,6 @@ import os
20
  import re
21
  from collections import Counter
22
  from dataclasses import asdict, dataclass
23
- from typing import Dict, List, Optional, Tuple
24
 
25
  import gradio as gr
26
 
@@ -39,14 +38,14 @@ class TaskDoc:
39
  file_path: str
40
  module: str
41
  abstract: str
42
- languages: List[str]
43
- tags: List[str]
44
- paper: Optional[str]
45
- dataset: Optional[str]
46
- name: Optional[str] = None
47
 
48
 
49
- def read_file_text(path: str) -> Optional[str]:
50
  try:
51
  with open(path, "r", encoding="utf-8") as f:
52
  return f.read()
@@ -54,7 +53,7 @@ def read_file_text(path: str) -> Optional[str]:
54
  return None
55
 
56
 
57
- def parse_module_docstring(text: str) -> Optional[str]:
58
  try:
59
  mod = ast.parse(text)
60
  return ast.get_docstring(mod)
@@ -64,11 +63,11 @@ def parse_module_docstring(text: str) -> Optional[str]:
64
  return m.group(2).strip() if m else None
65
 
66
 
67
- def parse_sections(doc: str) -> Dict[str, str]:
68
  # Very simple section parser keyed by lines ending with ':' on their own
69
  # Expected keys: name, dataset, abstract, languages, tags, paper
70
- out: Dict[str, str] = {"name": "", "dataset": "", "abstract": "", "languages": "", "tags": "", "paper": ""}
71
- current_key: Optional[str] = None
72
  for raw_line in doc.splitlines():
73
  line = raw_line.rstrip()
74
  if line.endswith(":") and line.strip().lower() in {"name:", "dataset:", "abstract:", "languages:", "tags:", "paper:"}:
@@ -80,12 +79,12 @@ def parse_sections(doc: str) -> Dict[str, str]:
80
  return out
81
 
82
 
83
- def split_list_field(value: str) -> List[str]:
84
  if not value:
85
  return []
86
  # Support comma and newline separated values
87
  parts = re.split(r"[\n,]", value)
88
- cleaned: List[str] = []
89
  for p in parts:
90
  token = p.strip()
91
  if not token:
@@ -94,8 +93,8 @@ def split_list_field(value: str) -> List[str]:
94
  return cleaned
95
 
96
 
97
- def discover_task_files() -> List[str]:
98
- files: List[str] = []
99
  for base in TASK_DIRS:
100
  if not os.path.isdir(base):
101
  continue
@@ -111,7 +110,7 @@ def discover_task_files() -> List[str]:
111
  files.append(os.path.join(dirpath, "main.py"))
112
  # Deduplicate while preserving order
113
  seen: set = set()
114
- unique_files: List[str] = []
115
  for p in files:
116
  if p in seen:
117
  continue
@@ -120,8 +119,8 @@ def discover_task_files() -> List[str]:
120
  return sorted(unique_files)
121
 
122
 
123
- def index_tasks() -> Tuple[List[TaskDoc], List[str], List[str]]:
124
- docs: List[TaskDoc] = []
125
  language_counts: Counter = Counter()
126
  tag_set: set = set()
127
  for path in discover_task_files():
@@ -151,7 +150,7 @@ def index_tasks() -> Tuple[List[TaskDoc], List[str], List[str]]:
151
  return docs, languages_sorted, tags_sorted
152
 
153
 
154
- def save_index(path: str, tasks: List[TaskDoc], langs: List[str], tags: List[str]) -> None:
155
  data = {
156
  "tasks": [asdict(t) for t in tasks],
157
  "languages": list(langs),
@@ -162,7 +161,7 @@ def save_index(path: str, tasks: List[TaskDoc], langs: List[str], tags: List[str
162
  json.dump(data, f, ensure_ascii=False, indent=2)
163
 
164
 
165
- def load_index(path: str) -> Optional[Tuple[List[TaskDoc], List[str], List[str]]]:
166
  if not os.path.exists(path):
167
  return None
168
  with open(path, "r", encoding="utf-8") as f:
@@ -173,7 +172,7 @@ def load_index(path: str) -> Optional[Tuple[List[TaskDoc], List[str], List[str]]
173
  return tasks, langs, tags
174
 
175
 
176
- def build_and_cache_index() -> Tuple[List[TaskDoc], List[str], List[str]]:
177
  tasks, langs, tags = index_tasks()
178
  save_index(CACHE_PATH, tasks, langs, tags)
179
  return tasks, langs, tags
@@ -190,11 +189,11 @@ print(f"Loaded {len(ALL_TASKS)} tasks from cache")
190
  TOP_LANGS = ALL_LANGS[:8] # show more by default
191
 
192
 
193
- def filter_tasks(languages: List[str], tags: List[str], search: str) -> List[TaskDoc]:
194
  selected_langs = [lang.lower() for lang in (languages or [])]
195
  selected_tags = [t.lower() for t in (tags or [])]
196
  search_lc = (search or "").strip().lower()
197
- out: List[TaskDoc] = []
198
  for td in ALL_TASKS:
199
  if selected_langs and not any(lang in td.languages for lang in selected_langs):
200
  continue
@@ -209,9 +208,9 @@ def filter_tasks(languages: List[str], tags: List[str], search: str) -> List[Tas
209
  return out
210
 
211
 
212
- def render_cards(tasks: List[TaskDoc]) -> str:
213
  # Responsive grid of pretty cards; show all details without clicks
214
- items: List[str] = []
215
  for t in tasks:
216
  parts = t.module.replace("\\", "/").split("/")
217
  base_no_ext = parts[-1].rsplit(".", 1)[0]
@@ -313,21 +312,21 @@ def render_cards(tasks: List[TaskDoc]) -> str:
313
  return style + "<div class=\"cards-grid\">" + "\n".join(items) + "</div>"
314
 
315
 
316
- def on_filter(languages: List[str], tags: List[str], search: str):
317
  tasks = filter_tasks(languages, tags, search)
318
  return render_cards(tasks)
319
 
320
 
321
- def on_toggle_language_choices(show_all: bool, selected_langs: List[str], tags: List[str], search: str):
322
  choices = ALL_LANGS if show_all else TOP_LANGS
323
  kept = [lang for lang in (selected_langs or []) if lang in choices]
324
  tasks = filter_tasks(kept, tags, search)
325
  return gr.update(choices=choices, value=kept), render_cards(tasks)
326
 
327
 
328
- def on_toggle_tags_visibility(show: bool, selected_tags: List[str], languages: List[str], search: str):
329
  # Only toggle visibility; preserve current tag selections and keep them active in filtering
330
- tags_value: List[str] = selected_tags or []
331
  tasks = filter_tasks(languages, tags_value, search)
332
  # keep selections when showing; when hiding we keep value but component hidden (so filter still uses them)
333
  return gr.update(visible=show, value=tags_value), render_cards(tasks)
 
20
  import re
21
  from collections import Counter
22
  from dataclasses import asdict, dataclass
 
23
 
24
  import gradio as gr
25
 
 
38
  file_path: str
39
  module: str
40
  abstract: str
41
+ languages: list[str]
42
+ tags: list[str]
43
+ paper: str | None
44
+ dataset: str | None
45
+ name: str | None = None
46
 
47
 
48
+ def read_file_text(path: str) -> str | None:
49
  try:
50
  with open(path, "r", encoding="utf-8") as f:
51
  return f.read()
 
53
  return None
54
 
55
 
56
+ def parse_module_docstring(text: str) -> str | None:
57
  try:
58
  mod = ast.parse(text)
59
  return ast.get_docstring(mod)
 
63
  return m.group(2).strip() if m else None
64
 
65
 
66
+ def parse_sections(doc: str) -> dict[str, str]:
67
  # Very simple section parser keyed by lines ending with ':' on their own
68
  # Expected keys: name, dataset, abstract, languages, tags, paper
69
+ out: dict[str, str] = {"name": "", "dataset": "", "abstract": "", "languages": "", "tags": "", "paper": ""}
70
+ current_key: str | None = None
71
  for raw_line in doc.splitlines():
72
  line = raw_line.rstrip()
73
  if line.endswith(":") and line.strip().lower() in {"name:", "dataset:", "abstract:", "languages:", "tags:", "paper:"}:
 
79
  return out
80
 
81
 
82
+ def split_list_field(value: str) -> list[str]:
83
  if not value:
84
  return []
85
  # Support comma and newline separated values
86
  parts = re.split(r"[\n,]", value)
87
+ cleaned: list[str] = []
88
  for p in parts:
89
  token = p.strip()
90
  if not token:
 
93
  return cleaned
94
 
95
 
96
+ def discover_task_files() -> list[str]:
97
+ files: list[str] = []
98
  for base in TASK_DIRS:
99
  if not os.path.isdir(base):
100
  continue
 
110
  files.append(os.path.join(dirpath, "main.py"))
111
  # Deduplicate while preserving order
112
  seen: set = set()
113
+ unique_files: list[str] = []
114
  for p in files:
115
  if p in seen:
116
  continue
 
119
  return sorted(unique_files)
120
 
121
 
122
+ def index_tasks() -> tuple[list[TaskDoc], list[str], list[str]]:
123
+ docs: list[TaskDoc] = []
124
  language_counts: Counter = Counter()
125
  tag_set: set = set()
126
  for path in discover_task_files():
 
150
  return docs, languages_sorted, tags_sorted
151
 
152
 
153
+ def save_index(path: str, tasks: list[TaskDoc], langs: list[str], tags: list[str]) -> None:
154
  data = {
155
  "tasks": [asdict(t) for t in tasks],
156
  "languages": list(langs),
 
161
  json.dump(data, f, ensure_ascii=False, indent=2)
162
 
163
 
164
+ def load_index(path: str) -> tuple[list[TaskDoc], list[str], list[str]] | None:
165
  if not os.path.exists(path):
166
  return None
167
  with open(path, "r", encoding="utf-8") as f:
 
172
  return tasks, langs, tags
173
 
174
 
175
+ def build_and_cache_index() -> tuple[list[TaskDoc], list[str], list[str]]:
176
  tasks, langs, tags = index_tasks()
177
  save_index(CACHE_PATH, tasks, langs, tags)
178
  return tasks, langs, tags
 
189
  TOP_LANGS = ALL_LANGS[:8] # show more by default
190
 
191
 
192
+ def filter_tasks(languages: list[str], tags: list[str], search: str) -> list[TaskDoc]:
193
  selected_langs = [lang.lower() for lang in (languages or [])]
194
  selected_tags = [t.lower() for t in (tags or [])]
195
  search_lc = (search or "").strip().lower()
196
+ out: list[TaskDoc] = []
197
  for td in ALL_TASKS:
198
  if selected_langs and not any(lang in td.languages for lang in selected_langs):
199
  continue
 
208
  return out
209
 
210
 
211
+ def render_cards(tasks: list[TaskDoc]) -> str:
212
  # Responsive grid of pretty cards; show all details without clicks
213
+ items: list[str] = []
214
  for t in tasks:
215
  parts = t.module.replace("\\", "/").split("/")
216
  base_no_ext = parts[-1].rsplit(".", 1)[0]
 
312
  return style + "<div class=\"cards-grid\">" + "\n".join(items) + "</div>"
313
 
314
 
315
+ def on_filter(languages: list[str], tags: list[str], search: str):
316
  tasks = filter_tasks(languages, tags, search)
317
  return render_cards(tasks)
318
 
319
 
320
+ def on_toggle_language_choices(show_all: bool, selected_langs: list[str], tags: list[str], search: str):
321
  choices = ALL_LANGS if show_all else TOP_LANGS
322
  kept = [lang for lang in (selected_langs or []) if lang in choices]
323
  tasks = filter_tasks(kept, tags, search)
324
  return gr.update(choices=choices, value=kept), render_cards(tasks)
325
 
326
 
327
+ def on_toggle_tags_visibility(show: bool, selected_tags: list[str], languages: list[str], search: str):
328
  # Only toggle visibility; preserve current tag selections and keep them active in filtering
329
+ tags_value: list[str] = selected_tags or []
330
  tasks = filter_tasks(languages, tags_value, search)
331
  # keep selections when showing; when hiding we keep value but component hidden (so filter still uses them)
332
  return gr.update(visible=show, value=tags_value), render_cards(tasks)