-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathexceptions.py
More file actions
189 lines (138 loc) · 5.61 KB
/
Copy pathexceptions.py
File metadata and controls
189 lines (138 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
from .core import ffi as _ffi
from .core import lib as _lib
from .core.utils import _Pointer
from .core.utils import libget as _libget
class GraphblasException(Exception):
pass
class NoValue(GraphblasException):
pass
class UninitializedObject(GraphblasException):
pass
class InvalidObject(GraphblasException):
"""One of the collection objects (input or output)
is in an invalid state due to a previous error.
"""
class NullPointer(GraphblasException):
pass
class InvalidValue(GraphblasException):
pass
class InvalidIndex(GraphblasException):
"""Provided index specifies a location outside the dimensions.
This error is always raised immediately, even in non-blocking mode.
"""
class DomainMismatch(GraphblasException):
"""The domains (i.e. data types) of the inputs or outputs
are incompatible for the operation.
"""
class DimensionMismatch(GraphblasException):
"""The input or output dimensions (i.e. shape) are not compatible."""
class OutputNotEmpty(GraphblasException):
"""Attempt to call :meth:`~graphblas.Matrix.build` on a non-empty object."""
class OutOfMemory(GraphblasException):
"""GraphBLAS ran out of memory when allocating space for the operation."""
class InsufficientSpace(GraphblasException):
pass
class IndexOutOfBound(GraphblasException):
"""A provided index falls outside the dimensions.
In non-blocking mode, this error can be deferred.
"""
class Panic(GraphblasException):
"""Unknown internal GraphBLAS error."""
class EmptyObject(GraphblasException):
"""A provided Scalar object is empty, but requires a value.
This could happen, for example, if an empty Scalar is provided as the
``right`` argument to :meth:`~graphblas.Matrix.apply`.
"""
class NotImplementedException(GraphblasException):
"""The backend GraphBLAS implementation does not support
the operation for the provided inputs.
"""
# SuiteSparse errors
class JitError(GraphblasException):
"""SuiteSparse:GraphBLAS error using JIT."""
# Our errors
class UdfParseError(GraphblasException):
"""Raised when a UDF can't be compiled for the requested operand types.
Wraps Numba compilation errors (``TypingError``, ``LoweringError``,
``UnsupportedError``) into a single graphblas-level exception with the
actionable diagnostic line surfaced from Numba's traceback. Common
causes: an operator that doesn't exist for the field type
(``binary.floordiv`` on a complex field), a UDF that returns a tuple
whose length doesn't match any input UDT, or use of a Python construct
Numba doesn't support in nopython mode.
"""
# Warnings
class NoJITWarning(UserWarning):
"""Auto-lifted UDT op fell back to the Numba cfunc path.
Emitted from :func:`graphblas.core.ss.jit_config._maybe_warn_no_jit`
when an op like ``binary.plus[udt]`` would otherwise have JIT-compiled,
but couldn't because the JIT compiler is unusable, ``jit_c_control``
is off, or the UDT isn't expressible as a C struct. Fires once per
``(op, dtype)`` pair per process, so a user who registers several
UDTs gets one warning per pair regardless of cause.
Inherits from :class:`UserWarning` so existing ``UserWarning`` filters
still match it; users can also filter by category for a tight scope:
``warnings.filterwarnings("ignore", category=NoJITWarning)``.
"""
_error_code_lookup = {
# Warning
_lib.GrB_NO_VALUE: NoValue,
# API Errors
_lib.GrB_UNINITIALIZED_OBJECT: UninitializedObject,
_lib.GrB_INVALID_OBJECT: InvalidObject,
_lib.GrB_NULL_POINTER: NullPointer,
_lib.GrB_INVALID_VALUE: InvalidValue,
_lib.GrB_INVALID_INDEX: InvalidIndex,
_lib.GrB_DOMAIN_MISMATCH: DomainMismatch,
_lib.GrB_DIMENSION_MISMATCH: DimensionMismatch,
_lib.GrB_OUTPUT_NOT_EMPTY: OutputNotEmpty,
_lib.GrB_EMPTY_OBJECT: EmptyObject,
# Execution Errors
_lib.GrB_OUT_OF_MEMORY: OutOfMemory,
_lib.GrB_INSUFFICIENT_SPACE: InsufficientSpace,
_lib.GrB_INDEX_OUT_OF_BOUNDS: IndexOutOfBound,
_lib.GrB_PANIC: Panic,
_lib.GrB_NOT_IMPLEMENTED: NotImplementedException,
}
GrB_SUCCESS = _lib.GrB_SUCCESS
GrB_NO_VALUE = _lib.GrB_NO_VALUE
# SuiteSparse-specific errors
if hasattr(_lib, "GxB_EXHAUSTED"):
_error_code_lookup[_lib.GxB_EXHAUSTED] = StopIteration
if hasattr(_lib, "GxB_JIT_ERROR"): # Added in 9.4
_error_code_lookup[_lib.GxB_JIT_ERROR] = JitError
def check_status(response_code, args):
if response_code == GrB_SUCCESS:
return
if response_code == GrB_NO_VALUE:
return NoValue
if isinstance(args, list):
arg = args[0]
else:
arg = args
if hasattr(arg, "_exc_arg"):
arg = arg._exc_arg
if type(arg) is _Pointer:
arg = arg.val
type_name = type(arg).__name__
carg = arg._carg
return check_status_carg(response_code, type_name, carg)
def check_status_carg(response_code, type_name, carg):
if response_code == GrB_SUCCESS:
return
if response_code == GrB_NO_VALUE: # pragma: no cover (safety)
return NoValue
try:
error_func = _libget(f"GrB_{type_name}_error")
except AttributeError: # pragma: no cover (sanity)
text = (
f"Unable to get the error string for type {type_name}. "
"This is most likely a bug in graphblas. Please report this as an issue at:\n"
" https://github.com/python-graphblas/python-graphblas/issues\n"
"Thanks (and sorry)!"
)
else:
string = _ffi.new("char**")
error_func(string, carg)
text = _ffi.string(string[0]).decode()
raise _error_code_lookup[response_code](text)