Replace batch DAG system with streaming architecture
- Remove legacy_tasks.py, hybrid_state.py, render.py - Remove old task modules (analyze, execute, execute_sexp, orchestrate) - Add streaming interpreter from test repo - Add sexp_effects with primitives and video effects - Add streaming Celery task with CID-based asset resolution - Support both CID and friendly name references for assets - Add .dockerignore to prevent local clones from conflicting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
102
sexp_effects/primitive_libs/__init__.py
Normal file
102
sexp_effects/primitive_libs/__init__.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
Primitive Libraries System
|
||||
|
||||
Provides modular loading of primitives. Core primitives are always available,
|
||||
additional primitive libraries can be loaded on-demand with scoped availability.
|
||||
|
||||
Usage in sexp:
|
||||
;; Load at recipe level - available throughout
|
||||
(primitives math :path "primitive_libs/math.py")
|
||||
|
||||
;; Or use with-primitives for scoped access
|
||||
(with-primitives "image"
|
||||
(blur frame 3)) ;; blur only available inside
|
||||
|
||||
;; Nested scopes work
|
||||
(with-primitives "math"
|
||||
(with-primitives "color"
|
||||
(hue-shift frame (* (sin t) 30))))
|
||||
|
||||
Library file format (primitive_libs/math.py):
|
||||
import math
|
||||
|
||||
def prim_sin(x): return math.sin(x)
|
||||
def prim_cos(x): return math.cos(x)
|
||||
|
||||
PRIMITIVES = {
|
||||
'sin': prim_sin,
|
||||
'cos': prim_cos,
|
||||
}
|
||||
"""
|
||||
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
from typing import Dict, Callable, Any, Optional
|
||||
|
||||
# Cache of loaded primitive libraries
|
||||
_library_cache: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
# Core primitives - always available, cannot be overridden
|
||||
CORE_PRIMITIVES: Dict[str, Any] = {}
|
||||
|
||||
|
||||
def register_core_primitive(name: str, fn: Callable):
|
||||
"""Register a core primitive that's always available."""
|
||||
CORE_PRIMITIVES[name] = fn
|
||||
|
||||
|
||||
def load_primitive_library(name: str, path: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Load a primitive library by name or path.
|
||||
|
||||
Args:
|
||||
name: Library name (e.g., "math", "image", "color")
|
||||
path: Optional explicit path to library file
|
||||
|
||||
Returns:
|
||||
Dict of primitive name -> function
|
||||
"""
|
||||
# Check cache first
|
||||
cache_key = path or name
|
||||
if cache_key in _library_cache:
|
||||
return _library_cache[cache_key]
|
||||
|
||||
# Find library file
|
||||
if path:
|
||||
lib_path = Path(path)
|
||||
else:
|
||||
# Look in standard locations
|
||||
lib_dir = Path(__file__).parent
|
||||
lib_path = lib_dir / f"{name}.py"
|
||||
|
||||
if not lib_path.exists():
|
||||
raise ValueError(f"Primitive library '{name}' not found at {lib_path}")
|
||||
|
||||
if not lib_path.exists():
|
||||
raise ValueError(f"Primitive library file not found: {lib_path}")
|
||||
|
||||
# Load the module
|
||||
spec = importlib.util.spec_from_file_location(f"prim_lib_{name}", lib_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
# Get PRIMITIVES dict from module
|
||||
if not hasattr(module, 'PRIMITIVES'):
|
||||
raise ValueError(f"Primitive library '{name}' missing PRIMITIVES dict")
|
||||
|
||||
primitives = module.PRIMITIVES
|
||||
|
||||
# Cache and return
|
||||
_library_cache[cache_key] = primitives
|
||||
return primitives
|
||||
|
||||
|
||||
def get_library_names() -> list:
|
||||
"""Get names of available primitive libraries."""
|
||||
lib_dir = Path(__file__).parent
|
||||
return [p.stem for p in lib_dir.glob("*.py") if p.stem != "__init__"]
|
||||
|
||||
|
||||
def clear_cache():
|
||||
"""Clear the library cache (useful for testing)."""
|
||||
_library_cache.clear()
|
||||
Reference in New Issue
Block a user