Adds IndexBinaryOp and fixes for JIT by jim22k · Pull Request #576 · python-graphblas/python-graphblas
Summary
This commit adds full IndexBinaryOp UDT support and a suite of SuiteSparse JIT reliability fixes.
New Features
IndexBinaryOp on User-Defined Types (UDTs)
IndexBinaryOp._compile_udtnow works for UDT operands, including UDTthetavalues. A new_get_udt_wrapper_indexbinaryhelper inbase.pygenerates the Numba cfunc wrapper for the 4-index + theta signature (x, ix, jx, y, iy, jy, theta → z)._BoundIndexBinaryOp(the result ofibo[dtype](theta)) gained pickling support via__reduce__, proper type markers (_is_udt,commutes_to, etc.), and stores_thetafor round-trip serialization.ParameterizedIndexBinaryOppickle/deserialize now round-trips theis_udtflag.
JIT C Code Generation for UDTs (udt_utils.py — new file, ~979 lines)
- Generates C struct typedefs from numpy dtypes (record and array UDTs), enabling SuiteSparse to JIT-compile optimized kernels instead of falling back to Numba cfuncs.
- Handles nested record UDTs, array UDTs, C-reserved name collisions (synthesizes
_gbudt_NNNnames automatically), and complex-type field restrictions. - Provides
_compile_codegen— a safeexec-based helper with AST pre-validation andlinecacheregistration for readable tracebacks.
JIT Config Auto-Repair (jit_config.py — new file)
fix_jit_config(): replaces conda-build-baked compiler paths with one from$CONDA_PREFIX/bin/orsysconfig, strips stale-isysroot/-fdebug-prefix-mapflags, and optionally probes the result with a trivial JIT compile._auto_fix_jit_at_import(): called automatically atgb.ssimport time to silently repair common mis-configurations without user intervention.jit_compiler_is_usable(): lightweight check (file existence only) for use in warnings.
DataType JIT Introspection
- New
jit_c_nameandjit_c_definitionproperties expose the C type name and struct typedef that SuiteSparse actually registered — stable across Python-side renames. _set_udt_jit_c_definition()setsGxB_JIT_C_NAME+GxB_JIT_C_DEFINITIONon theGrB_Typeat registration time.
register_new / register_anonymous Ergonomics
- Both now accept a bare
@dataclassclass or instance as the sole argument, inferringnamefrom the class name.
Fixes & Improvements
UDT Wrapper Refactor (base.py)
_get_udt_wrapperwas a large monolithic function; it's been decomposed into_input_operand,_output_handler, and_compose_wrapper_body, handling record UDTs (tuple-unpack returns), array UDTs, and BOOL-as-INT8 coercion correctly in all combinations._resolve_udt_return_typeresolves NumbaBaseTuplereturn types back to the matching record UDT by field arity and type alignment, with actionableUdfParseErrormessages when the match fails.
Better UDF Error Messages
UdfParseErrordocstring updated to document wrapping ofTypingError,LoweringError,UnsupportedError._compile_udf_for_udtcatches the fullNumbaErrorhierarchy and surfaces the actionable diagnostic line (via_summarize_numba_typing_error) rather than a raw Numba traceback.- New
NoJITWarningwarning class emitted once per process when an auto-lifted UDT op falls back to the cfunc path (JIT compiler unusable,jit_c_controloff, or UDT not C-representable).
Scalar / UDT Thunk Binding
TypedBuiltinIndexBinaryOp.__call__storestheta_valuebefore wrapping in aScalar, fixing a round-trip issue for UDT thunks whereScalar.from_valuecouldn't infer the dtype from a raw numpy array.
Tests & Docs
test_indexbinary.pyexpanded with UDT cases, pickling, and semiring round-trips.test_op.pyadded ~1,200 lines covering UDT operator compilation, JIT codegen, and error paths.test_ssjit.pyexpanded with JIT auto-fix,NoJITWarning, and C typedef generation tests.test_dtype.pyandtest_pickle.pyextended for newjit_c_name/jit_c_definitionandregister_new(dataclass)behaviour.- New user guide pages:
udt.rst(UDT reference) and updatedudf.rstandoperators.rst.