Spaces:
Running
on
T4
Running
on
T4
#!/usr/bin/env python3 | |
""" | |
Hugging Face Spaces Entry Point | |
This file must remain in root for HF Spaces compatibility | |
Imports and runs the main application from core/app.py | |
""" | |
# --- BEGIN ABSOLUTE-IMPORT & ENV HOTFIX (Hugging Face) --- | |
import os, re, io, sys | |
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) # /home/user/app | |
# Ensure top-level packages are importable (utils, core, models, processing) | |
if PROJECT_ROOT not in sys.path: | |
sys.path.insert(0, PROJECT_ROOT) | |
# Quiet invalid OMP_NUM_THREADS warnings (libgomp) | |
val = os.environ.get("OMP_NUM_THREADS") | |
if val is not None and not str(val).strip().isdigit(): | |
# Either unset or set to a safe default; we set to 1 | |
os.environ["OMP_NUM_THREADS"] = "1" | |
def _patch_relative_imports(project_root: str): | |
""" | |
Rewrite 'from ..X.y' -> 'from X.y' for top-level packages. | |
Runs once at startup; safe/no-op if already fixed. | |
""" | |
skip_dirs = {"venv", ".git", "__pycache__"} | |
rx_from = re.compile(r"(?m)^from\s+\.+(utils|core|models|processing)\.") | |
touched = [] | |
for root, dirs, files in os.walk(project_root): | |
# prune | |
dirs[:] = [d for d in dirs if d not in skip_dirs] | |
for fn in files: | |
if not fn.endswith(".py"): | |
continue | |
path = os.path.join(root, fn) | |
try: | |
with io.open(path, "r", encoding="utf-8") as f: | |
src = f.read() | |
new = rx_from.sub(r"from \1.", src) | |
if new != src: | |
with io.open(path, "w", encoding="utf-8") as f: | |
f.write(new) | |
touched.append(os.path.relpath(path, project_root)) | |
except Exception: | |
# Don't block startup if a file can't be read/written | |
pass | |
if touched: | |
print(f"✅ Fixed relative imports in {len(touched)} file(s):") | |
for p in touched: | |
print(" -", p) | |
_patch_relative_imports(PROJECT_ROOT) | |
# --- END ABSOLUTE-IMPORT & ENV HOTFIX --- | |
# --- BEGIN robust compatibility: ensure 'utilities' references the real utils package ---------- | |
# Some legacy modules import `utilities`. We will ensure sys.modules['utilities'] points | |
# to the same module object as 'utils' by: | |
# 1) Attempting a normal import of utils; if that works, alias it. | |
# 2) If normal import fails or would recurse, fall back to loading utils/__init__.py | |
# directly via importlib.util.spec_from_file_location, placing the module object | |
# into sys.modules BEFORE executing the module to avoid circular lazy-swaps. | |
import importlib | |
import importlib.util | |
from types import ModuleType | |
def _ensure_utilities_alias(project_root: str): | |
# If utilities already exists and isn't obviously broken, leave it alone. | |
if "utilities" in sys.modules and getattr(sys.modules["utilities"], "__name__", "").startswith("utils"): | |
return | |
# Try normal import first (fast path) | |
try: | |
_utils = importlib.import_module("utils") | |
sys.modules["utilities"] = _utils | |
return | |
except Exception: | |
# proceed to robust file-loader fallback below | |
pass | |
# Fallback: load utils package explicitly from filesystem using its __init__.py | |
utils_init = os.path.join(project_root, "utils", "__init__.py") | |
if not os.path.exists(utils_init): | |
# nothing we can do here — leave to normal import to raise error later | |
return | |
spec = importlib.util.spec_from_file_location("utils", utils_init) | |
if spec is None or spec.loader is None: | |
return | |
# Create the module object and put it in sys.modules BEFORE execution. | |
# This ensures imports within utils that examine sys.modules won't re-enter a cycle. | |
utils_mod = importlib.util.module_from_spec(spec) | |
sys.modules["utils"] = utils_mod | |
# Also alias utilities -> utils_mod so imports of utilities see the same module object. | |
sys.modules["utilities"] = utils_mod | |
# Execute the module (this will run utils/__init__.py) | |
try: | |
spec.loader.exec_module(utils_mod) # type: ignore[attr-defined] | |
except Exception: | |
# If execution fails, remove the partially-initialized entries so Python's import machinery can surface a clean error. | |
sys.modules.pop("utils", None) | |
sys.modules.pop("utilities", None) | |
raise | |
# Ensure alias early, before importing core | |
_ensure_utilities_alias(PROJECT_ROOT) | |
# --- END robust compatibility ------------------------------------------------ | |
# Import the main application from core | |
from core.app import ( | |
VideoProcessor, | |
processor, | |
load_models_with_validation, | |
process_video_fixed, | |
get_model_status, | |
get_cache_status, | |
PROCESS_CANCELLED, | |
main, | |
) | |
# Re-export for backward compatibility | |
__all__ = [ | |
"VideoProcessor", | |
"processor", | |
"load_models_with_validation", | |
"process_video_fixed", | |
"get_model_status", | |
"get_cache_status", | |
"PROCESS_CANCELLED", | |
"main", | |
] | |
# Entry point for Hugging Face Spaces | |
if __name__ == "__main__": | |
main() | |