Spaces:
Sleeping
Sleeping
| """Feature μλ νμ + λ±λ‘. | |
| features/ νμ λλ ν 리λ₯Ό μ€μΊνμ¬ FEATURE_CONFIGκ° μλ λͺ¨λμ μμ§νκ³ orderλ‘ μ λ ¬. | |
| """ | |
| import importlib | |
| from pathlib import Path | |
| _REQUIRED_CONFIG_FIELDS = {"name", "icon", "order"} | |
| def discover_features() -> list[dict]: | |
| """features/ νμ λλ ν 리λ₯Ό μ€μΊ, FEATURE_CONFIG μλ λͺ¨λ μμ§, order μ λ ¬. | |
| Returns: | |
| List of dicts with 'config' and 'module' keys, sorted by order. | |
| """ | |
| features_dir = Path(__file__).parent / "features" | |
| if not features_dir.exists(): | |
| return [] | |
| results = [] | |
| for child in sorted(features_dir.iterdir()): | |
| if not child.is_dir() or child.name.startswith("_"): | |
| continue | |
| init_file = child / "__init__.py" | |
| if not init_file.exists(): | |
| continue | |
| try: | |
| module = importlib.import_module(f"features.{child.name}") | |
| config = getattr(module, "FEATURE_CONFIG", None) | |
| if not config or not isinstance(config, dict): | |
| continue | |
| missing = _REQUIRED_CONFIG_FIELDS - set(config.keys()) | |
| if missing: | |
| import streamlit as st | |
| st.warning(f"Feature '{child.name}': νμ νλ λλ½ {missing}") | |
| continue | |
| if not hasattr(module, "render") or not callable(module.render): | |
| import streamlit as st | |
| st.warning(f"Feature '{child.name}': render() ν¨μ μμ") | |
| continue | |
| results.append({ | |
| "config": config, | |
| "module": module, | |
| }) | |
| except Exception as e: | |
| import streamlit as st | |
| st.warning( | |
| f"Feature '{child.name}' λ‘λ μ€ν¨: " | |
| f"{type(e).__name__}: {e}" | |
| ) | |
| results.sort(key=lambda x: x["config"].get("order", 99)) | |
| return results | |