""" Backend detection and configuration for diff-diff. This module handles: 1. Detection of optional Rust backend 2. Environment variable configuration (DIFF_DIFF_BACKEND) 3. Exports HAS_RUST_BACKEND and Rust function references Other modules should import from here to avoid circular imports with __init__.py. """ import os # Check for backend override via environment variable # DIFF_DIFF_BACKEND can be: 'auto' (default), 'python', or 'rust' _backend_env = os.environ.get("DIFF_DIFF_BACKEND", "auto").lower() # Try to import Rust backend for accelerated operations try: from diff_diff._rust_backend import ( generate_bootstrap_weights_batch as _rust_bootstrap_weights, project_simplex as _rust_project_simplex, solve_ols as _rust_solve_ols, compute_robust_vcov as _rust_compute_robust_vcov, # TROP estimator acceleration (local method) compute_unit_distance_matrix as _rust_unit_distance_matrix, loocv_grid_search as _rust_loocv_grid_search, bootstrap_trop_variance as _rust_bootstrap_trop_variance, # TROP estimator acceleration (global method) loocv_grid_search_global as _rust_loocv_grid_search_global, bootstrap_trop_variance_global as _rust_bootstrap_trop_variance_global, # SDID weights (Frank-Wolfe matching R's synthdid) compute_sdid_unit_weights as _rust_sdid_unit_weights, compute_time_weights as _rust_compute_time_weights, compute_noise_level as _rust_compute_noise_level, sc_weight_fw as _rust_sc_weight_fw, sc_weight_fw_with_convergence as _rust_sc_weight_fw_with_convergence, sc_weight_fw_weighted as _rust_sc_weight_fw_weighted, sc_weight_fw_weighted_with_convergence as _rust_sc_weight_fw_weighted_with_convergence, # Diagnostics rust_backend_info as _rust_backend_info, ) _rust_available = True except ImportError: _rust_available = False _rust_bootstrap_weights = None _rust_project_simplex = None _rust_solve_ols = None _rust_compute_robust_vcov = None # TROP estimator acceleration (local method) _rust_unit_distance_matrix = None _rust_loocv_grid_search = None _rust_bootstrap_trop_variance = None # TROP estimator acceleration (global method) _rust_loocv_grid_search_global = None _rust_bootstrap_trop_variance_global = None # SDID weights (Frank-Wolfe matching R's synthdid) _rust_sdid_unit_weights = None _rust_compute_time_weights = None _rust_compute_noise_level = None _rust_sc_weight_fw = None _rust_sc_weight_fw_with_convergence = None _rust_sc_weight_fw_weighted = None _rust_sc_weight_fw_weighted_with_convergence = None _rust_backend_info = None # Determine final backend based on environment variable and availability if _backend_env == "python": # Force pure Python mode - disable Rust even if available HAS_RUST_BACKEND = False _rust_bootstrap_weights = None _rust_project_simplex = None _rust_solve_ols = None _rust_compute_robust_vcov = None # TROP estimator acceleration (local method) _rust_unit_distance_matrix = None _rust_loocv_grid_search = None _rust_bootstrap_trop_variance = None # TROP estimator acceleration (global method) _rust_loocv_grid_search_global = None _rust_bootstrap_trop_variance_global = None # SDID weights (Frank-Wolfe matching R's synthdid) _rust_sdid_unit_weights = None _rust_compute_time_weights = None _rust_compute_noise_level = None _rust_sc_weight_fw = None _rust_sc_weight_fw_with_convergence = None _rust_sc_weight_fw_weighted = None _rust_sc_weight_fw_weighted_with_convergence = None _rust_backend_info = None elif _backend_env == "rust": # Force Rust mode - fail if not available if not _rust_available: raise ImportError( "DIFF_DIFF_BACKEND=rust but Rust backend is not available. " "Install with: pip install diff-diff[rust]" ) HAS_RUST_BACKEND = True else: # Auto mode - use Rust if available HAS_RUST_BACKEND = _rust_available def rust_backend_info(): """Return compile-time BLAS feature information for the Rust backend. Returns a dict with keys: - 'blas': True if any BLAS backend is linked - 'accelerate': True if Apple Accelerate is linked (macOS) - 'openblas': True if OpenBLAS is linked (Linux) If the Rust backend is not available, all values are False. """ if _rust_backend_info is not None: return _rust_backend_info() return {"blas": False, "accelerate": False, "openblas": False} __all__ = [ "HAS_RUST_BACKEND", "rust_backend_info", "_rust_bootstrap_weights", "_rust_project_simplex", "_rust_solve_ols", "_rust_compute_robust_vcov", # TROP estimator acceleration (local method) "_rust_unit_distance_matrix", "_rust_loocv_grid_search", "_rust_bootstrap_trop_variance", # TROP estimator acceleration (global method) "_rust_loocv_grid_search_global", "_rust_bootstrap_trop_variance_global", # SDID weights (Frank-Wolfe matching R's synthdid) "_rust_sdid_unit_weights", "_rust_compute_time_weights", "_rust_compute_noise_level", "_rust_sc_weight_fw", "_rust_sc_weight_fw_with_convergence", "_rust_sc_weight_fw_weighted", "_rust_sc_weight_fw_weighted_with_convergence", ]