From f8827cdff67dd89b0550da2b28372b0810e2dec3 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Tue, 20 Dec 2022 11:10:16 -0600 Subject: [PATCH] Remove pygraphblas conversions (#348) `pygraphblas` appears to be defunct, and we have been unable to test these conversions for a very long time. I don't think it's necessary to deprecate these first, since they are and have been unusable. The benefit of this is cleaner code, cleaner tab-completion, and easier maintenance. We can revisit this if `pygraphblas` is ever revived (but I hope we can redirect effort to `python-graphblas`, which I believe is much further along in development). --- .github/workflows/test_and_build.yml | 15 ++------ .pre-commit-config.yaml | 10 ++--- graphblas/core/automethods.py | 5 --- graphblas/core/infix.py | 3 -- graphblas/core/matrix.py | 48 ------------------------ graphblas/core/scalar.py | 37 ------------------- graphblas/core/vector.py | 47 ------------------------ graphblas/tests/test_matrix.py | 4 +- graphblas/tests/test_pygraphblas.py | 55 ---------------------------- graphblas/tests/test_scalar.py | 2 - graphblas/tests/test_vector.py | 2 - 11 files changed, 9 insertions(+), 219 deletions(-) delete mode 100644 graphblas/tests/test_pygraphblas.py diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 2b54dcfa9..c323a331c 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -58,8 +58,8 @@ jobs: auto-activate-base: false - name: Update env run: | - mamba install -c conda-forge pytest coverage 'black>=20.8b1' flake8 \ - coveralls pytest-randomly flake8-comprehensions flake8-bugbear + mamba install -c conda-forge pytest coverage black flake8 \ + coveralls=3.3.1 pytest-randomly flake8-comprehensions flake8-bugbear - name: Style Checks run: | flake8 @@ -87,18 +87,11 @@ jobs: mamba install -c conda-forge python-suitesparse-graphblas fi python setup.py develop --no-deps - # - name: Optional pygraphblas - # if: contains(matrix.cfg.testopts, 'pygraphblas') && (matrix.cfg.pyver != 3.9) - # run: | - # source "$CONDA/etc/profile.d/conda.sh" - # conda activate graphblas - # mamba install -c conda-forge pygraphblas - name: Verify build run: | # Make sure all top-level imports work ./scripts/test_imports.sh - name: Unit tests - # if: (! contains(matrix.cfg.testopts, 'pygraphblas')) || (matrix.cfg.pyver != 3.9) run: | coverage run --branch -m pytest ${{ matrix.cfg.testopts }} -v # Run tests again with Scalars being C scalars by default @@ -130,7 +123,6 @@ jobs: git diff --exit-code coverage xml - name: Coverage - # if: (! contains(matrix.cfg.testopts, 'pygraphblas')) || (matrix.cfg.pyver != 3.9) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COVERALLS_FLAG_NAME: ${{ matrix.cfg.pyver}}/${{ matrix.cfg.testopts }} @@ -141,7 +133,6 @@ jobs: - name: codecov uses: codecov/codecov-action@v3 - name: Notebooks Execution check - # if: (! contains(matrix.cfg.testopts, 'pygraphblas')) || (matrix.cfg.pyver != 3.9) run: | mamba install -c conda-forge matplotlib nbconvert jupyter 'ipython>=7' jupyter nbconvert --to notebook --execute notebooks/*ipynb @@ -156,7 +147,7 @@ jobs: source "$CONDA/etc/profile.d/conda.sh" conda config --set always_yes yes --set changeps1 no conda update -q conda - conda create -n coveralls_final -c conda-forge python=3.9 coveralls + conda create -n coveralls_final -c conda-forge python=3.9 coveralls=3.3.1 - name: Coveralls Finished env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 78071c33f..eabde8bd3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,26 +18,26 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/myint/autoflake - rev: v1.7.7 + rev: v2.0.0 hooks: - id: autoflake args: [--in-place] - repo: https://github.com/pycqa/isort - rev: 5.10.1 + rev: v5.11.3 hooks: - id: isort language_version: python3 - repo: https://github.com/asottile/pyupgrade - rev: v3.2.2 + rev: v3.3.1 hooks: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/MarcoGorelli/auto-walrus - rev: v0.2.1 + rev: v0.2.2 hooks: - id: auto-walrus - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 22.12.0 hooks: - id: black language_version: python3 diff --git a/graphblas/core/automethods.py b/graphblas/core/automethods.py index 7ef2f1b75..57dbb87a3 100644 --- a/graphblas/core/automethods.py +++ b/graphblas/core/automethods.py @@ -273,10 +273,6 @@ def to_dicts(self): return self._get_value("to_dicts") -def to_pygraphblas(self): - return self._get_value("to_pygraphblas") - - def to_values(self): return self._get_value("to_values") @@ -352,7 +348,6 @@ def _main(): "isequal", "name", "nvals", - "to_pygraphblas", "wait", } scalar = { diff --git a/graphblas/core/infix.py b/graphblas/core/infix.py index 55636d65d..5eccdfa06 100644 --- a/graphblas/core/infix.py +++ b/graphblas/core/infix.py @@ -98,7 +98,6 @@ def shape(self): ss = wrapdoc(Vector.ss)(property(automethods.ss)) to_coo = wrapdoc(Vector.to_coo)(property(automethods.to_coo)) to_dict = wrapdoc(Vector.to_dict)(property(automethods.to_dict)) - to_pygraphblas = wrapdoc(Vector.to_pygraphblas)(property(automethods.to_pygraphblas)) to_values = wrapdoc(Vector.to_values)(property(automethods.to_values)) vxm = wrapdoc(Vector.vxm)(property(automethods.vxm)) wait = wrapdoc(Vector.wait)(property(automethods.wait)) @@ -226,7 +225,6 @@ def shape(self): to_dcsc = wrapdoc(Matrix.to_dcsc)(property(automethods.to_dcsc)) to_dcsr = wrapdoc(Matrix.to_dcsr)(property(automethods.to_dcsr)) to_dicts = wrapdoc(Matrix.to_dicts)(property(automethods.to_dicts)) - to_pygraphblas = wrapdoc(Matrix.to_pygraphblas)(property(automethods.to_pygraphblas)) to_values = wrapdoc(Matrix.to_values)(property(automethods.to_values)) wait = wrapdoc(Matrix.wait)(property(automethods.wait)) # These raise exceptions @@ -335,7 +333,6 @@ def is_grbscalar(self): name = wrapdoc(Scalar.name)(property(automethods.name)) name = name.setter(automethods._set_name) nvals = wrapdoc(Scalar.nvals)(property(automethods.nvals)) - to_pygraphblas = wrapdoc(Scalar.to_pygraphblas)(property(automethods.to_pygraphblas)) value = wrapdoc(Scalar.value)(property(automethods.value)) wait = wrapdoc(Scalar.wait)(property(automethods.wait)) # These raise exceptions diff --git a/graphblas/core/matrix.py b/graphblas/core/matrix.py index c61592c92..b0bf124b3 100644 --- a/graphblas/core/matrix.py +++ b/graphblas/core/matrix.py @@ -2915,52 +2915,6 @@ def _delete_element(self, resolved_indexes): rowidx, colidx = resolved_indexes.indices call("GrB_Matrix_removeElement", [self, rowidx.index, colidx.index]) - def to_pygraphblas(self): # pragma: no cover (outdated) - """Convert to a ``pygraphblas.Matrix`` without copying data. - - This gives control of the underlying GraphBLAS memory to pygraphblas, - meaning further operations on the current :class:`Matrix` object will fail! - - This method requires the - `pygraphblas `_ - library to be installed. - """ - if backend != "suitesparse": - raise RuntimeError( - f"to_pygraphblas only works with 'suitesparse' backend, not {backend}" - ) - import pygraphblas as pg - - matrix = pg.Matrix(self.gb_obj, pg.types._gb_type_to_type(self.dtype.gb_obj)) - self.gb_obj = ffi_new("GrB_Matrix*") - return matrix - - @classmethod - def from_pygraphblas(cls, matrix): # pragma: no cover (outdated) - """Convert a ``pygraphblas.Matrix`` to a new :class:`Matrix` without copying data. - - This gives control of the underlying GraphBLAS memory to python-graphblas, - meaning further operations on the original ``pygraphblas`` matrix object will fail! - - This method requires the - `pygraphblas `_ - library to be installed. - """ - if backend != "suitesparse": - raise RuntimeError( - f"from_pygraphblas only works with 'suitesparse' backend, not {backend!r}" - ) - import pygraphblas as pg - - if not isinstance(matrix, pg.Matrix): - raise TypeError(f"Expected pygraphblas.Matrix object. Got type: {type(matrix)}") - dtype = lookup_dtype(matrix.gb_type) - rv = cls(matrix._matrix, dtype) - rv._nrows = matrix.nrows - rv._ncols = matrix.ncols - matrix._matrix = ffi_new("GrB_Matrix*") - return rv - if backend == "suitesparse": Matrix.ss = class_property(Matrix.ss, ss) @@ -3121,7 +3075,6 @@ def shape(self): to_dcsc = wrapdoc(Matrix.to_dcsc)(property(automethods.to_dcsc)) to_dcsr = wrapdoc(Matrix.to_dcsr)(property(automethods.to_dcsr)) to_dicts = wrapdoc(Matrix.to_dicts)(property(automethods.to_dicts)) - to_pygraphblas = wrapdoc(Matrix.to_pygraphblas)(property(automethods.to_pygraphblas)) to_values = wrapdoc(Matrix.to_values)(property(automethods.to_values)) wait = wrapdoc(Matrix.wait)(property(automethods.wait)) # These raise exceptions @@ -3211,7 +3164,6 @@ def shape(self): to_dcsc = wrapdoc(Matrix.to_dcsc)(property(automethods.to_dcsc)) to_dcsr = wrapdoc(Matrix.to_dcsr)(property(automethods.to_dcsr)) to_dicts = wrapdoc(Matrix.to_dicts)(property(automethods.to_dicts)) - to_pygraphblas = wrapdoc(Matrix.to_pygraphblas)(property(automethods.to_pygraphblas)) to_values = wrapdoc(Matrix.to_values)(property(automethods.to_values)) wait = wrapdoc(Matrix.wait)(property(automethods.wait)) # These raise exceptions diff --git a/graphblas/core/scalar.py b/graphblas/core/scalar.py index a3b7d84be..30c303310 100644 --- a/graphblas/core/scalar.py +++ b/graphblas/core/scalar.py @@ -549,41 +549,6 @@ def __reduce__(self): def _deserialize(value, dtype, is_cscalar, name): return Scalar.from_value(value, dtype, is_cscalar=is_cscalar, name=name) - def to_pygraphblas(self): # pragma: no cover (outdated) - """Convert to a ``pygraphblas.Scalar`` by making a copy of the internal value. - - This method requires the - `pygraphblas `_ - library to be installed. - """ - if backend != "suitesparse": - raise RuntimeError( - f"to_pygraphblas only works with 'suitesparse' backend, not {backend}" - ) - import pygraphblas as pg - - return pg.Scalar.from_value(self.value) - - @classmethod - def from_pygraphblas(cls, scalar): # pragma: no cover (outdated) - """Convert a ``pygraphblas.Scalar`` to a new :class:`Scalar` by making - a copy of the internal value. - - This method requires the - `pygraphblas `_ - library to be installed. - """ - if backend != "suitesparse": - raise RuntimeError( - f"from_pygraphblas only works with 'suitesparse' backend, not {backend!r}" - ) - import pygraphblas as pg - - if not isinstance(scalar, pg.Scalar): - raise TypeError(f"Expected pygraphblas.Scalar object. Got type: {type(scalar)}") - dtype = lookup_dtype(scalar.gb_type) - return cls.from_value(scalar[0], dtype) - def _as_vector(self, *, name=None): """Copy or cast this Scalar to a Vector @@ -688,7 +653,6 @@ def _repr_html_(self): name = wrapdoc(Scalar.name)(property(automethods.name)) name = name.setter(automethods._set_name) nvals = wrapdoc(Scalar.nvals)(property(automethods.nvals)) - to_pygraphblas = wrapdoc(Scalar.to_pygraphblas)(property(automethods.to_pygraphblas)) value = wrapdoc(Scalar.value)(property(automethods.value)) wait = wrapdoc(Scalar.wait)(property(automethods.wait)) # These raise exceptions @@ -749,7 +713,6 @@ def is_grbscalar(self): name = wrapdoc(Scalar.name)(property(automethods.name)) name = name.setter(automethods._set_name) nvals = wrapdoc(Scalar.nvals)(property(automethods.nvals)) - to_pygraphblas = wrapdoc(Scalar.to_pygraphblas)(property(automethods.to_pygraphblas)) value = wrapdoc(Scalar.value)(property(automethods.value)) wait = wrapdoc(Scalar.wait)(property(automethods.wait)) # These raise exceptions diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index f8ec3301a..91f1a6c6a 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -1714,51 +1714,6 @@ def _delete_element(self, resolved_indexes): idx = resolved_indexes.indices[0] call("GrB_Vector_removeElement", [self, idx.index]) - def to_pygraphblas(self): # pragma: no cover (outdated) - """Convert to a ``pygraphblas.Vector`` without copying data. - - This gives control of the underlying GraphBLAS memory to pygraphblas, - meaning further operations on the current :class:`Vector` object will fail! - - This method requires the - `pygraphblas `_ - library to be installed. - """ - if backend != "suitesparse": - raise RuntimeError( - f"to_pygraphblas only works with 'suitesparse' backend, not {backend}" - ) - import pygraphblas as pg - - vector = pg.Vector(self.gb_obj, pg.types._gb_type_to_type(self.dtype.gb_obj)) - self.gb_obj = ffi_new("GrB_Vector*") - return vector - - @classmethod - def from_pygraphblas(cls, vector): # pragma: no cover (outdated) - """Convert a ``pygraphblas.Vector`` to a new :class:`Vector` without copying data. - - This gives control of the underlying GraphBLAS memory to python-graphblas, - meaning further operations on the original ``pygraphblas`` vector object will fail! - - This method requires the - `pygraphblas `_ - library to be installed. - """ - if backend != "suitesparse": - raise RuntimeError( - f"from_pygraphblas only works with 'suitesparse' backend, not {backend!r}" - ) - import pygraphblas as pg - - if not isinstance(vector, pg.Vector): - raise TypeError(f"Expected pygraphblas.Vector object. Got type: {type(vector)}") - dtype = lookup_dtype(vector.gb_type) - rv = cls(vector._vector, dtype) - rv._size = vector.size - vector._vector = ffi_new("GrB_Vector*") - return rv - @classmethod def from_dict(cls, d, dtype=None, *, size=None, name=None): """Create a new Vector from a dict with keys as indices and values as values. @@ -1919,7 +1874,6 @@ def shape(self): ss = wrapdoc(Vector.ss)(property(automethods.ss)) to_coo = wrapdoc(Vector.to_coo)(property(automethods.to_coo)) to_dict = wrapdoc(Vector.to_dict)(property(automethods.to_dict)) - to_pygraphblas = wrapdoc(Vector.to_pygraphblas)(property(automethods.to_pygraphblas)) to_values = wrapdoc(Vector.to_values)(property(automethods.to_values)) vxm = wrapdoc(Vector.vxm)(property(automethods.vxm)) wait = wrapdoc(Vector.wait)(property(automethods.wait)) @@ -1995,7 +1949,6 @@ def shape(self): ss = wrapdoc(Vector.ss)(property(automethods.ss)) to_coo = wrapdoc(Vector.to_coo)(property(automethods.to_coo)) to_dict = wrapdoc(Vector.to_dict)(property(automethods.to_dict)) - to_pygraphblas = wrapdoc(Vector.to_pygraphblas)(property(automethods.to_pygraphblas)) to_values = wrapdoc(Vector.to_values)(property(automethods.to_values)) vxm = wrapdoc(Vector.vxm)(property(automethods.vxm)) wait = wrapdoc(Vector.wait)(property(automethods.wait)) diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index a5044adc5..ef973e25e 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -2889,7 +2889,6 @@ def test_expr_is_like_matrix(A): "from_dcsc", "from_dcsr", "from_dicts", - "from_pygraphblas", "from_values", "resize", "update", @@ -2905,7 +2904,7 @@ def test_expr_is_like_matrix(A): # so maybe it shouldn't support everything. if suitesparse: expected.add("ss") - assert attrs - transposed_attrs == (expected | {"_as_vector", "S", "V", "to_pygraphblas"}) - { + assert attrs - transposed_attrs == (expected | {"_as_vector", "S", "V"}) - { "_prep_for_extract", "_extract_element", } @@ -2942,7 +2941,6 @@ def test_index_expr_is_like_matrix(A): "from_dcsc", "from_dcsr", "from_dicts", - "from_pygraphblas", "from_values", "resize", } diff --git a/graphblas/tests/test_pygraphblas.py b/graphblas/tests/test_pygraphblas.py deleted file mode 100644 index 1f062a07f..000000000 --- a/graphblas/tests/test_pygraphblas.py +++ /dev/null @@ -1,55 +0,0 @@ -import pytest - -import graphblas as gb - -try: - import pygraphblas as pg -except ImportError: - pg = None - - -@pytest.mark.skipif("not pg") -def test_pygraphblas_matrix(): # pragma: no cover (outdated) - if gb.backend != "suitesparse": # pragma: no cover - return - import pygraphblas as pg - - A = gb.Matrix.from_coo([0, 1], [0, 1], [0, 1]) - pgA = A.to_pygraphblas() - assert isinstance(pgA, pg.Matrix) - assert A.gb_obj is gb.core.NULL - pgA += 1 - A2 = gb.Matrix.from_pygraphblas(pgA) - assert A2.isequal(gb.Matrix.from_coo([0, 1], [0, 1], [1, 2])) - assert A.dtype == A2.dtype - - -@pytest.mark.skipif("not pg") -def test_pygraphblas_vector(): # pragma: no cover (outdated) - if gb.backend != "suitesparse": # pragma: no cover - return - import pygraphblas as pg - - v = gb.Vector.from_coo([0, 2], [0, 1]) - pgv = v.to_pygraphblas() - assert isinstance(pgv, pg.Vector) - assert v.gb_obj is gb.core.NULL - pgv += 1 - v2 = gb.Vector.from_pygraphblas(pgv) - assert v2.isequal(gb.Vector.from_coo([0, 2], [1, 2])) - assert v.dtype == v2.dtype - - -@pytest.mark.skipif("not pg") -def test_pygraphblas_scalar(): # pragma: no cover (outdated) - if gb.backend != "suitesparse": # pragma: no cover - return - import pygraphblas as pg - - s = gb.Scalar.from_value(1) - pgs = s.to_pygraphblas() - assert isinstance(pgs, pg.Scalar) - assert pgs.nvals == 1 - s2 = gb.Scalar.from_pygraphblas(pgs) - assert s2 == 1 - assert s.dtype == s2.dtype diff --git a/graphblas/tests/test_scalar.py b/graphblas/tests/test_scalar.py index 19eb4e890..4f104dbb0 100644 --- a/graphblas/tests/test_scalar.py +++ b/graphblas/tests/test_scalar.py @@ -338,7 +338,6 @@ def test_expr_is_like_scalar(s): "_name_counter", "_update", "clear", - "from_pygraphblas", "from_value", "update", } @@ -370,7 +369,6 @@ def test_index_expr_is_like_scalar(s): "_name_counter", "_update", "clear", - "from_pygraphblas", "from_value", } if s.is_cscalar: diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index cdc461e2e..cdc462eff 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -1599,7 +1599,6 @@ def test_expr_is_like_vector(v): "clear", "from_coo", "from_dict", - "from_pygraphblas", "from_values", "resize", "update", @@ -1636,7 +1635,6 @@ def test_index_expr_is_like_vector(v): "clear", "from_coo", "from_dict", - "from_pygraphblas", "from_values", "resize", }