Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion graphblas/core/ss/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,5 @@ def __repr__(self):
+ "})"
)

def _ipython_key_completions_(self): # pragma: no cover (ipython)
def _ipython_key_completions_(self):
return list(self)
53 changes: 53 additions & 0 deletions graphblas/tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,41 @@ def test_from_networkx_rejects_array_weights(graph_cls):
gb.io.from_networkx(G)


@pytest.mark.skipif("not nx or not ss")
@pytest.mark.parametrize(
"graph_cls", [nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph] if nx else []
)
def test_from_networkx_rejects_string_weights(graph_cls):
# String weights infer a 1-D <U array, so a shape test alone would let them
# through; only the dtype-kind half of the guard sends these to scipy, which
# rejects them the way it always has.
G = graph_cls()
G.add_edge(0, 1, weight="a")
G.add_edge(1, 2, weight="b")
with pytest.raises(ValueError, match="does not support dtype"):
gb.io.from_networkx(G)


@pytest.mark.skipif("not nx")
def test_from_networkx_unsupported_dtype_is_valueerror(monkeypatch):
# scipy < 1.15 builds a string-dtype coo array happily and only fails converting
# it to csr, and networkx re-raises that failure as a NetworkXError blaming the
# sparse format. from_networkx restates it as the ValueError newer scipy raises
# directly, which is what the caller can act on; monkeypatching the fallback
# exercises the old behavior on any scipy.
import graphblas.io._networkx as _gnx

def _raise_networkx_error(*args, **kwargs):
raise nx.NetworkXError("Unknown sparse matrix format: csr")

monkeypatch.setattr(_gnx, "_from_networkx_via_scipy", _raise_networkx_error)
G = nx.Graph()
G.add_edge(0, 1, weight="a")
G.add_edge(1, 2, weight="b")
with pytest.raises(ValueError, match="does not support dtype"):
gb.io.from_networkx(G)


@pytest.mark.skipif("not nx or not ss")
@pytest.mark.parametrize(
"graph_cls", [nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph] if nx else []
Expand Down Expand Up @@ -460,6 +495,24 @@ def test_matrix_market_bad_engine():
gb.io.mmread(mm_out, engine="bad_engine")


@pytest.mark.skipif("not ss")
@pytest.mark.skipif("fmm is not None")
def test_matrix_market_fmm_engine_unavailable():
# Naming the deprecated engine warns before anything else, so the caller hears
# about the deprecation even when the install that would satisfy it is missing.
A = gb.Matrix.from_coo([0, 0, 3, 5], [1, 4, 0, 2], [1, 0, 2, -1], nrows=7, ncols=6)
with (
pytest.warns(DeprecationWarning, match="fast_matrix_market is no longer maintained"),
pytest.raises(ImportError, match="required to write Matrix Market files"),
):
gb.io.mmwrite(BytesIO(), A, engine="fmm")
with (
pytest.warns(DeprecationWarning, match="fast_matrix_market is no longer maintained"),
pytest.raises(ImportError, match="required to read Matrix Market files"),
):
gb.io.mmread(BytesIO(), engine="fast_matrix_market")


@pytest.mark.skipif("not ss")
def test_scipy_sparse():
a = np.arange(12).reshape(3, 4)
Expand Down
16 changes: 16 additions & 0 deletions graphblas/tests/test_ss_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,22 @@ def test_global_config():
assert "format" in repr(config)


def test_global_config_key_completions():
# IPython offers these for `config[<tab>]`, so they must be the keys that
# actually resolve, not the attributes of the mapping object.
config = gb.ss.config
completions = config._ipython_key_completions_()
assert set(completions) == set(config._options)
for key in completions:
config[key]
# About aliases the same hook onto its own __iter__ (gb.ss.about[<tab>])
about = gb.ss.about
completions = about._ipython_key_completions_()
assert set(completions) == set(about)
for key in completions:
about[key]


@pytest.mark.skipif("gb.core.ss._IS_SSGB7")
def test_context():
context = gb.ss.Context()
Expand Down