Skip to content
Merged
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
5 changes: 1 addition & 4 deletions .github/workflows/test_and_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,8 @@ jobs:
# conda install -c conda-forge pygraphblas
- name: Verify build
run: |
# Make sure `from graphblas import *` works as expected
python -c "from graphblas import * ; Matrix"
# Make sure all top-level imports work
( for attr in Matrix Scalar Vector Recorder _agg agg base binary descriptor dtypes exceptions expr ffi formatting infix init io lib mask matrix monoid op operator scalar semiring tests unary vector recorder _ss ss ; do echo python -c \"from graphblas import $attr\" ; if ! python -c "from graphblas import $attr" ; then exit 1 ; fi ; done )
( for attr in _agg agg base binary descriptor dtypes exceptions expr formatting infix io mask matrix monoid op operator scalar semiring tests unary vector recorder _ss ss ; do echo python -c \"import graphblas.$attr\" ; if ! python -c "import graphblas.$attr" ; then exit 1 ; fi ; done )
./scripts/test_imports.sh
- name: Unit tests
# if: (! contains(matrix.cfg.testopts, 'pygraphblas')) || (matrix.cfg.pyver != 3.9)
run: |
Expand Down
52 changes: 4 additions & 48 deletions graphblas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import sys as _sys
from importlib import import_module as _import_module
from importlib.abc import Loader as _Loader
from importlib.abc import MetaPathFinder as _MetaPathFinder

from . import mask # noqa
from ._version import get_versions
Expand Down Expand Up @@ -156,17 +154,8 @@ def _init(backend_arg, blocking, automatic=False):
_init_params = passed_params


_NEEDS_OPERATOR = {
"graphblas._agg",
"graphblas.agg",
"graphblas.base",
"graphblas.io",
"graphblas.matrix",
"graphblas.scalar",
"graphblas.vector",
"graphblas.recorder",
"graphblas.ss",
}
# Ideally this is in operator.py, but lives here to avoid circular references
_STANDARD_OPERATOR_NAMES = set()


def _load(name):
Expand All @@ -175,44 +164,11 @@ def _load(name):
if module_name not in globals():
_load(module_name)
module = globals()[module_name]
val = getattr(module, name)
globals()[name] = val
globals()[name] = getattr(module, name)
else:
# Everything else is a module
module = _import_module(f".{name}", __name__)
globals()[name] = module
spec = module.__spec__
if not isinstance(spec.loader, _SkipLoad):
# Make sure we execute the module only once
spec.loader = _SkipLoad(module, spec.loader)


class _GraphblasModuleFinder(_MetaPathFinder):
def find_spec(self, fullname, path, target=None):
if fullname in _NEEDS_OPERATOR and "operator" not in globals():
_load("operator")
name = fullname[7:] # Trim "graphblas."
if name in globals(): # pragma: no cover
# Make sure we execute the module only once
module = globals()[name]
spec = module.__spec__
spec.loader = _SkipLoad(module, spec.loader)
return spec


class _SkipLoad(_Loader):
def __init__(self, module, orig_loader):
self.module = module
self.orig_loader = orig_loader

def create_module(self, spec):
return self.module

def exec_module(self, module):
pass

globals()[name] = _import_module(f".{name}", __name__)

_sys.meta_path.insert(0, _GraphblasModuleFinder())

__version__ = get_versions()["version"]
del get_versions
Expand Down
8 changes: 5 additions & 3 deletions graphblas/_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

from . import agg, binary, monoid, semiring, unary
from .dtypes import INT64, lookup_dtype
from .operator import get_typed_op
from .scalar import Scalar


def _get_types(ops, initdtype):
Expand Down Expand Up @@ -124,7 +122,7 @@ def _new(self, updater, expr, *, in_composite=False):
if agg._monoid is not None:
x = expr.args[0]
method = getattr(x, expr.method_name)
if expr.output_type is Scalar:
if expr.output_type.__name__ == "Scalar":
expr = method(agg._monoid[self.type], allow_empty=not expr._is_cscalar)
else:
expr = method(agg._monoid[self.type])
Expand Down Expand Up @@ -621,3 +619,7 @@ def _first_last_index(agg, updater, expr, *, in_composite, semiring):
types=[semiring.min_secondi],
any_dtype=INT64,
)
agg.Aggregator = Aggregator
agg.TypedAggregator = TypedAggregator

from .operator import get_typed_op # noqa isort:skip
7 changes: 3 additions & 4 deletions graphblas/_ss/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -3580,8 +3580,6 @@ def scan_columnwise(self, op=monoid.plus, *, name=None):
-------
Vector
"""
from .prefix_scan import prefix_scan

return prefix_scan(self._parent.T, op, name=name, within="scan_columnwise")

def scan_rowwise(self, op=monoid.plus, *, name=None):
Expand All @@ -3594,8 +3592,6 @@ def scan_rowwise(self, op=monoid.plus, *, name=None):
-------
Vector
"""
from .prefix_scan import prefix_scan

return prefix_scan(self._parent, op, name=name, within="scan_rowwise")

def flatten(self, order="rowwise", *, name=None):
Expand Down Expand Up @@ -4230,3 +4226,6 @@ def indptr_to_indices(indptr): # pragma: no cover
for j in range(indptr[i], indptr[i + 1]):
indices[j] = i
return indices


from .prefix_scan import prefix_scan # noqa isort:skip
5 changes: 4 additions & 1 deletion graphblas/agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,7 @@
"""
# All items are dynamically added by classes in _agg.py
# This module acts as a container of Aggregator instances
from ._agg import Aggregator, TypedAggregator # noqa
from . import operator

del operator
from . import _agg # noqa isort:skip
10 changes: 6 additions & 4 deletions graphblas/binary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
"rfloordiv": "floordiv",
"rpow": "pow",
}
from graphblas import operator # noqa isort:skip
from . import numpy # noqa isort:skip

del operator


def __dir__():
Expand All @@ -32,3 +28,9 @@ def __getattr__(key):
rv._commutes_to = other
return rv
raise AttributeError(f"module {__name__!r} has no attribute {key!r}")


from .. import operator # noqa isort:skip
from . import numpy # noqa isort:skip

del operator
8 changes: 5 additions & 3 deletions graphblas/binary/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"""
import numpy as _np

from .. import _STANDARD_OPERATOR_NAMES
from .. import binary as _binary
from .. import config as _config
from .. import operator as _operator

_delayed = {}
_binary_names = {
Expand Down Expand Up @@ -56,7 +56,7 @@
"nextafter",
"ldexp",
}
_operator._STANDARD_OPERATOR_NAMES.update(f"binary.numpy.{name}" for name in _binary_names)
_STANDARD_OPERATOR_NAMES.update(f"binary.numpy.{name}" for name in _binary_names)
__all__ = list(_binary_names)
_numpy_to_graphblas = {
# Monoids
Expand Down Expand Up @@ -140,8 +140,10 @@ def __getattr__(name):
if _config.get("mapnumpy") and name in _numpy_to_graphblas:
globals()[name] = getattr(_binary, _numpy_to_graphblas[name])
else:
from .. import operator

numpy_func = getattr(_np, name)
_operator.BinaryOp.register_new(f"numpy.{name}", lambda x, y: numpy_func(x, y))
operator.BinaryOp.register_new(f"numpy.{name}", lambda x, y: numpy_func(x, y))
rv = globals()[name]
if name in _commutative:
rv._commutes_to = rv
Expand Down
3 changes: 1 addition & 2 deletions graphblas/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from . import lib, utils
from .dtypes import _INDEX
from .mask import Mask
from .utils import _CArray, output_type


Expand Down Expand Up @@ -231,8 +232,6 @@ def parse_index(self, index, typ, size):
try:
index = list(index)
except Exception:
from .mask import Mask

if isinstance(index, Mask):
raise TypeError(
f"Invalid type for index: {typ.__name__}.\n"
Expand Down
8 changes: 5 additions & 3 deletions graphblas/indexunary/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# All items are dynamically added by classes in operator.py
# This module acts as a container of IndexUnaryOp instances
_delayed = {}
from graphblas import operator # noqa isort:skip

del operator


def __dir__():
Expand All @@ -17,3 +14,8 @@ def __getattr__(key):
globals()[key] = rv
return rv
raise AttributeError(f"module {__name__!r} has no attribute {key!r}")


from .. import operator # noqa isort:skip

del operator
17 changes: 10 additions & 7 deletions graphblas/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
from .expr import AmbiguousAssignOrExtract, IndexerResolver, Updater
from .mask import StructuralMask, ValueMask
from .operator import find_opclass, get_semiring, get_typed_op, op_from_string
from .scalar import _MATERIALIZE, Scalar, ScalarExpression, _as_scalar, _scalar_index
from .scalar import (
_MATERIALIZE,
Scalar,
ScalarExpression,
ScalarIndexExpr,
_as_scalar,
_scalar_index,
)
from .utils import (
_CArray,
_Pointer,
Expand All @@ -21,7 +28,7 @@
values_to_numpy_buffer,
wrapdoc,
)
from .vector import Vector, VectorExpression
from .vector import Vector, VectorExpression, VectorIndexExpr

ffi_new = ffi.new

Expand Down Expand Up @@ -142,12 +149,8 @@ def __getitem__(self, keys):
resolved_indexes = IndexerResolver(self, keys)
shape = resolved_indexes.shape
if not shape:
from .scalar import ScalarIndexExpr

return ScalarIndexExpr(self, resolved_indexes)
elif len(shape) == 1:
from .vector import VectorIndexExpr

return VectorIndexExpr(self, resolved_indexes, *shape)
else:
return MatrixIndexExpr(self, resolved_indexes, *shape)
Expand Down Expand Up @@ -807,7 +810,7 @@ def apply(self, op, right=None, *, left=None):
expr_repr = "{1.name}.apply({op}, left={0._expr_name})"
elif left is None:
if type(right) is not Scalar:
dtype = self.dtype if self.dtype._is_udt else None
dtype = self.dtype if (self.dtype._is_udt and not op.is_positional) else None
try:
right = Scalar.from_value(right, dtype, is_cscalar=None, name="")
except TypeError:
Expand Down
10 changes: 6 additions & 4 deletions graphblas/monoid/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# All items are dynamically added by classes in operator.py
# This module acts as a container of Monoid instances
_delayed = {}
from graphblas import operator # noqa isort:skip
from . import numpy # noqa isort:skip

del operator


def __dir__():
Expand All @@ -22,3 +18,9 @@ def __getattr__(key):
globals()[key] = rv
return rv
raise AttributeError(f"module {__name__!r} has no attribute {key!r}")


from .. import operator # noqa isort:skip
from . import numpy # noqa isort:skip

del operator
8 changes: 5 additions & 3 deletions graphblas/monoid/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
"""
import numpy as _np

from .. import _STANDARD_OPERATOR_NAMES
from .. import binary as _binary
from .. import config as _config
from .. import monoid as _monoid
from .. import operator as _operator
from ..dtypes import _supports_complex

_delayed = {}
Expand Down Expand Up @@ -98,7 +98,7 @@
)
_monoid_identities["minimum"].update(dict.fromkeys(_complex_dtypes, complex(_np.inf, _np.inf)))

_operator._STANDARD_OPERATOR_NAMES.update(f"monoid.numpy.{name}" for name in _monoid_identities)
_STANDARD_OPERATOR_NAMES.update(f"monoid.numpy.{name}" for name in _monoid_identities)
__all__ = list(_monoid_identities)
_numpy_to_graphblas = {
"add": "plus",
Expand Down Expand Up @@ -136,6 +136,8 @@ def __getattr__(name):
if _config.get("mapnumpy") and name in _numpy_to_graphblas:
globals()[name] = getattr(_monoid, _numpy_to_graphblas[name])
else:
from .. import operator

func = getattr(_binary.numpy, name)
_operator.Monoid.register_new(f"numpy.{name}", func, _monoid_identities[name])
operator.Monoid.register_new(f"numpy.{name}", func, _monoid_identities[name])
return globals()[name]
10 changes: 6 additions & 4 deletions graphblas/op/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# All items are dynamically added by classes in operator.py
# This module acts as a container of all UnaryOp, BinaryOp, and Semiring instances
_delayed = {}
from graphblas import operator # noqa isort:skip
from . import numpy # noqa isort:skip

del operator


def __dir__():
Expand All @@ -18,3 +14,9 @@ def __getattr__(key):
globals()[key] = rv
return rv
raise AttributeError(f"module {__name__!r} has no attribute {key!r}")


from .. import operator # noqa isort:skip
from . import numpy # noqa isort:skip

del operator
Loading