File size: 5,062 Bytes
58835e7
 
 
 
 
 
 
783cf8c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7cfe09f
43b448c
 
 
 
 
 
 
7cfe09f
43b448c
b39df64
7cfe09f
43b448c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7cfe09f
 
58835e7
 
 
 
 
 
 
 
 
783cf8c
58835e7
 
 
 
783cf8c
 
 
 
 
 
 
 
58835e7
 
 
 
783cf8c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/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()