Repository navigation
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## 16-asv-benchmarks #656 +/- ##
=====================================================
+ Coverage 98.86% 99.30% +0.44%
=====================================================
Files 109 109
Lines 32828 33019 +191
Branches 3746 3734 -12
=====================================================
+ Hits 32454 32791 +337
+ Misses 249 152 -97
+ Partials 125 76 -49 🚀 New features to boost your workflow:
|
eriknw
force-pushed
the
51-coverage-main-gaps
branch
from
October 28, 2026 13:21
2a430a5 to
cc828b8
Compare
…kling A bool field takes min's and max's identity as logical and/or; a date or text field has none, so the monoid names the field and the aggregator does not work with the UDT; a user monoid without an identity says so. A named monoid unpickled where its name is gone is registered again with its identity and is_idempotent. agg.sum[udt].jit_c_name follows its monoid. The name check in _scalar_identity and the initializer's lookup, which no input reaches, get pragmas with the reason.
…rors Binding no theta binds 0, through the typed op or the op given a dtype; a C scalar or GraphBLAS scalar theta binds through either; a UDT-typed op given a value that is not one raises that value's TypeError. The typed op reports its parent's function. An op with no theta bound, UDT or not, is refused as an operator by reduce. Before SuiteSparse:GraphBLAS 9.4 both register_anonymous and indexbinary.ss.register_new say what is missing, and gb.indexbinary.ss is absent on the vanilla backend. The arms no IndexBinaryOp can reach, and a test's re-run cleanup, get pragmas with the reason.
… probing fix_jit_config(probe=False) enables the JIT without trying a compile. Without CONDA_PREFIX the compiler, flags and libraries come from sysconfig, and a Python that records no compiler gets None and an untouched config. A baked-in -isysroot that does not exist takes xcrun's SDK, or is dropped when there is no xcrun. The import-time repair leaves a SuiteSparse with no JIT options alone, and an error the control does not explain is re-raised as it came. All run against a stand-in config. The no-environment test drops CONDA_PREFIX with monkeypatch rather than by hand, so it has no branch that depends on the environment.
A name that is not an identifier, a typedef that does not declare the name, and a typedef of something other than a struct are refused with ValueError before SuiteSparse is asked to compile anything, and register nothing.
Setting bitmap_switch to the wrong number of values raises ValueError and leaves the setting as it was. This replaces the commented-out check on memory_pool, which is no longer an option. No option has an int64_t type since then, so those get and set arms get pragmas.
As test_vector.py's test_udt does for Vector: an anonymous UDT with a long numpy repr round-trips given dtype=, and a named one is found by its registered name.
CI does not install fast_matrix_market, so the engine was never used. A stand-in module that reads and writes with scipy plays it: engine "auto" and "fmm" both use it, each with its deprecation warning, and a version before 1.7 is given a scipy sparse matrix to write rather than an array.
Each gets a pragma with its reason, and a comment where the reason is not already written next to it: - dtypes: a UDT's C typedef is asked for only with its numpy type, and the explicit layout dict recurses only into records and arrays; - get_typed_op: two built-in types always unify, and a UDT beside another type returns before that; - typed op finalizer: the shutdown and no-free-function guards; - the GxB_EXHAUSTED check and the lookup of unary.abs and unary.ainv, which every supported build has.
Both operands of the outer | are themselves expressions: with the same dtype the inner typed op is reused, and with another dtype the result is promoted.
test_diag always passed nthreads, so the arm without options never ran.
The cross-process pickle tests unpickle and compute in a spawned child, which coverage does not measure; the pre-test cleanups run only when an earlier run in the same process left the name behind; the identity mismatch messages are built only on failure; and a stand-in lookup passes other keys through only if the code under test asks for them. The JIT parity check's comparison is one expression, so it has no failure-only line.
test_ss_pack_hyperhash packed the hash back only when SuiteSparse had computed one, which for its two rows SuiteSparse 8.2 does and 10.5 does not, so the pack arm ran on some CI draws only. With 1025 rows every version checked computes it (8.2.1, 10.5.0 and 10.5.1); the hash stays optional, so the guard stays, with a pragma.
Without Numba, applying unary.identity or unary.one to a UDT raises the usual KeyError that the op does not work with it.
SuiteSparse 10 refuses a blob whose encoding word asks for integer sizes larger than it knows, as a later version may write, when GrB_NAME's size is read from it, though it read the dtype name. A UDT Matrix blob edited so raises InvalidObject naming the read that failed (on SuiteSparse 9 the edit makes the type code invalid, and the dtype name read fails first). Reading GrB_NAME itself checks the blob as reading its size just did, so that status check gets a pragma.
The values of a full array-UDT Matrix carry its shape in their first two of three dimensions, and its export then leaves out nrows and ncols; an iso export has a single element, so importing it without nrows and ncols asks for them. That arm of get_shape is covered now, so its "BRANCH NOT COVERED" marker goes.
apply passes a UDT C scalar to GraphBLAS through a pointer object, and both the text and the HTML repr of the expression name the scalar, which the HTML one asks the pointer for.
eriknw
force-pushed
the
51-coverage-main-gaps
branch
from
October 29, 2026 02:01
cc828b8 to
71999d8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #596, below #651. Tests for lines on main that Codecov showed as never run, and
# pragma: no cover(orno branch) for the ones no input can reach. The library changesare pragmas and comments only, plus one stale "BRANCH NOT COVERED" comment removed: no
behavior changes here. The bugs these tests turned up are fixed in their own PRs lower in
the stack, or queued (below).
What the new tests cover:
identities; a date or text field, which has none, named in the monoid's KeyError, and
the aggregator not working with the UDT; a user monoid without an identity; a named
monoid unpickled after its name is gone, registered again with its identity and
is_idempotent;
agg.sum[udt].jit_c_namefollowing its monoid.typed op or the op given a dtype; C and GraphBLAS scalar thetas; a UDT-typed op given a
value that is not one; an op with no theta bound refused as an operator by reduce; the
errors before SuiteSparse:GraphBLAS 9.4;
gb.indexbinary.ssabsent on the vanillabackend.
fix_jit_config(probe=False), which enables the JIT without a test compile; noCONDA_PREFIX, so the compiler, flags and libraries come from sysconfig, or None when
Python records no compiler; a baked-in
-isysrootthat does not exist, with and withoutxcrun; the import-time repair on a SuiteSparse with no JIT options; an error the JIT
control does not explain re-raised as it came.
dtypes.ss.register_newrefusing a bad name or typedef beforeany compile; the element count check of array settings in
gb.ss.config(replacing acommented-out check on memory_pool, which is no longer an option);
Matrix.ss.serializeof a UDT whose name is too long for the blob; deserializing a blobwhose integer sizes SuiteSparse cannot read;
gb.ss.diagof a Vector without options;the shape of a full array-UDT import without nrows and ncols;
test_ss_pack_hyperhashwith 1025 rows, so SuiteSparse computes the hash on every version checked (8.2.1, 10.5.0
and 10.5.1), where with 2 rows the pack arm ran on some CI draws only.
install it, so that engine never ran); an infix ewise_add of two infix expressions;
unary.identity and unary.one on a UDT without Numba; the text and HTML reprs of an apply
naming its UDT scalar operand.
Each pragma carries a reason word,
(safety)for unreachable by construction,(defensive),(unused),(only on failure)or(child process), and a one-line commentwhere the reason is not already written beside it. In the library: a UDT's C typedef
asked for without its numpy type, the explicit layout of a dtype that is neither a record
nor an array,
get_typed_op's except arm, the typed op finalizer's shutdown guards,IndexBinaryOp guards that its builder already enforces,
_scalar_identitywith a nameother than min or max, the int64 config arms (no option has that type since memory_pool
went), a deserialize status check that the read before it already made, and lookups that
every supported build satisfies. In the tests: code that runs only in a spawned child
process (the cross-process pickle tests), on failure, or on a re-run in the same process.
Review tried to reach each excluded line; the four it could reach are tested or counted
again instead.
Bugs found, all on main too:
(v & v) & wwith sizes that differ raisedTypeError: _dummy() missing 1 required positional argumentinstead of DimensionMismatch, also for|and@: fixed inFix Scalar infix expressions with a literal operand #654.
np.iinfo, also from
udt in agg.min; a UDT monoid whose op returns another type raiseda DomainMismatch with no message;
Monoid.register_new(lazy=True)droppedis_idempotent; and a user op named plus, times, min or max got that built-in monoid's
generated identity, which gave wrong results silently: all four fixed in Extend the monoid guard to built-ins that carry a UDT fallback func #619.
max(x, y), whichuses
>) raised Numba's NotImplementedError at registration, and fromop["FC64"]and"FC64" in opwithis_udt=True: fixed in Learn built-in UDF return types by typing alone, defer the compiles #612.Queued, not fixed in this stack:
op()gives [2] whereop(0)gives [8]. Its docstring says the theta defaults to 0; thefix is a design choice.
AttributeError at registration; a clearer error would help.
datetime64 field does).
The same survey found why most of test_ssjit.py's JIT tests skip in CI. The compiler is
fine on Linux and macOS; psg's wheels build GraphBLAS without the JIT, and on Windows the
conda repair did not look where conda installs compilers. #636 now runs test_ssjit.py with
--runslowin the Linux and macOS notebooks jobs (and installs the psg version a wheel orsource draw picks, which had always been the newest), and #652 finds a
conda compiler on Windows.
Coverage, measured locally (suitesparse backend, Numba,
--runslow, the full suite) beforereview added three more tests: missed lines went from 926 to 836 and partial branches from
546 to 495, 95.90% to 96.32%. Most of what is left is covered only on other CI draws (older
SuiteSparse, vanilla, no Numba) or is #591's own code.
Every commit that adds tests was checked by breaking the code under test: 24 of 27 such
changes made the new test fail, and the other three changed nothing observable; the three
tests added in review each fail with their code broken. The touched
test files pass in random order with fixed seeds in eight configurations (including no
Numba on both backends, CI's C-scalar pass, numpy 2.2, SuiteSparse:GraphBLAS 8.2 and Python
3.15). The full suite passes with
--runslow, without Numba on both backends, and in theC-scalar pass; on Python 3.15, numpy 2.2 and SuiteSparse:GraphBLAS 8.2 the only failure is
test_version, from the local environments.