""" 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()