oprattr 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of oprattr might be problematic. Click here for more details.
- oprattr/__init__.py +7 -6
- oprattr/_operations.py +20 -22
- oprattr/abstract.py +56 -0
- oprattr/mixins.py +88 -14
- oprattr/operators.py +2 -2
- oprattr/typeface.py +42 -0
- oprattr/typeface.pyi +5 -0
- {oprattr-0.1.0.dist-info → oprattr-0.3.0.dist-info}/METADATA +3 -1
- oprattr-0.3.0.dist-info/RECORD +12 -0
- oprattr-0.3.0.dist-info/licenses/LICENSE +32 -0
- oprattr/_types.py +0 -144
- oprattr-0.1.0.dist-info/RECORD +0 -9
- {oprattr-0.1.0.dist-info → oprattr-0.3.0.dist-info}/WHEEL +0 -0
oprattr/__init__.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import collections.abc
|
|
1
2
|
import functools
|
|
2
3
|
import numbers
|
|
3
|
-
import typing
|
|
4
4
|
|
|
5
5
|
import numpy
|
|
6
6
|
|
|
7
|
+
from . import abstract
|
|
7
8
|
from . import mixins
|
|
8
9
|
from . import operators
|
|
9
|
-
from . import
|
|
10
|
+
from . import typeface
|
|
10
11
|
from ._operations import (
|
|
11
12
|
unary,
|
|
12
13
|
equality,
|
|
@@ -16,10 +17,10 @@ from ._operations import (
|
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
T =
|
|
20
|
+
T = typeface.TypeVar('T')
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
class Operand(
|
|
23
|
+
class Operand(abstract.Object[T], mixins.Numpy):
|
|
23
24
|
"""A concrete implementation of a real-valued object."""
|
|
24
25
|
|
|
25
26
|
def __abs__(self):
|
|
@@ -114,7 +115,7 @@ class Operand(_types.Object[T], mixins.Numpy):
|
|
|
114
115
|
|
|
115
116
|
def __rpow__(self, other):
|
|
116
117
|
"""Called for other ** self."""
|
|
117
|
-
return
|
|
118
|
+
return NotImplemented
|
|
118
119
|
|
|
119
120
|
def __array__(self, *args, **kwargs):
|
|
120
121
|
"""Called for numpy.array(self)."""
|
|
@@ -155,7 +156,7 @@ def gradient(x: Operand[T], *args, **kwargs):
|
|
|
155
156
|
return type(x)(data, **meta)
|
|
156
157
|
|
|
157
158
|
|
|
158
|
-
def wrapnumpy(f:
|
|
159
|
+
def wrapnumpy(f: collections.abc.Callable):
|
|
159
160
|
"""Implement a numpy function for objects with metadata."""
|
|
160
161
|
@functools.wraps(f)
|
|
161
162
|
def method(x: Operand[T], **kwargs):
|
oprattr/_operations.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
1
|
from . import operators
|
|
4
|
-
from .
|
|
2
|
+
from .abstract import Quantity
|
|
5
3
|
|
|
6
4
|
|
|
7
5
|
class MetadataError(TypeError):
|
|
@@ -11,8 +9,8 @@ class MetadataError(TypeError):
|
|
|
11
9
|
self,
|
|
12
10
|
f: operators.Operator,
|
|
13
11
|
*args,
|
|
14
|
-
error:
|
|
15
|
-
key:
|
|
12
|
+
error: str | None = None,
|
|
13
|
+
key: str | None = None,
|
|
16
14
|
) -> None:
|
|
17
15
|
super().__init__(*args)
|
|
18
16
|
self._f = f
|
|
@@ -33,8 +31,8 @@ class MetadataError(TypeError):
|
|
|
33
31
|
def _build_error_message(
|
|
34
32
|
f: operators.Operator,
|
|
35
33
|
*types: type,
|
|
36
|
-
error:
|
|
37
|
-
key:
|
|
34
|
+
error: str | None = None,
|
|
35
|
+
key: str | None = None,
|
|
38
36
|
) -> str:
|
|
39
37
|
"""Helper for `_raise_metadata_exception`.
|
|
40
38
|
|
|
@@ -50,9 +48,9 @@ def _build_error_message(
|
|
|
50
48
|
if len(types) == 2:
|
|
51
49
|
a, b = types
|
|
52
50
|
endstr = "because {} has metadata"
|
|
53
|
-
if issubclass(a,
|
|
51
|
+
if issubclass(a, Quantity):
|
|
54
52
|
return f"{errmsg} between {a} and {b} {endstr.format(str(a))}"
|
|
55
|
-
if issubclass(b,
|
|
53
|
+
if issubclass(b, Quantity):
|
|
56
54
|
return f"{errmsg} between {a} and {b} {endstr.format(str(b))}"
|
|
57
55
|
if errstr == 'type':
|
|
58
56
|
if key is None:
|
|
@@ -71,7 +69,7 @@ def _build_error_message(
|
|
|
71
69
|
|
|
72
70
|
def unary(f: operators.Operator, a):
|
|
73
71
|
"""Compute the unary operation f(a)."""
|
|
74
|
-
if isinstance(a,
|
|
72
|
+
if isinstance(a, Quantity):
|
|
75
73
|
meta = {}
|
|
76
74
|
for key, value in a._meta.items():
|
|
77
75
|
try:
|
|
@@ -86,15 +84,15 @@ def unary(f: operators.Operator, a):
|
|
|
86
84
|
|
|
87
85
|
def equality(f: operators.Operator, a, b):
|
|
88
86
|
"""Compute the equality operation f(a, b)."""
|
|
89
|
-
if isinstance(a,
|
|
87
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
90
88
|
if a._meta != b._meta:
|
|
91
89
|
return f is operators.ne
|
|
92
90
|
return f(a._data, b._data)
|
|
93
|
-
if isinstance(a,
|
|
91
|
+
if isinstance(a, Quantity):
|
|
94
92
|
if not a._meta:
|
|
95
93
|
return f(a._data, b)
|
|
96
94
|
return f is operators.ne
|
|
97
|
-
if isinstance(b,
|
|
95
|
+
if isinstance(b, Quantity):
|
|
98
96
|
if not b._meta:
|
|
99
97
|
return f(a, b._data)
|
|
100
98
|
return f is operators.ne
|
|
@@ -103,15 +101,15 @@ def equality(f: operators.Operator, a, b):
|
|
|
103
101
|
|
|
104
102
|
def ordering(f: operators.Operator, a, b):
|
|
105
103
|
"""Compute the ordering operation f(a, b)."""
|
|
106
|
-
if isinstance(a,
|
|
104
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
107
105
|
if a._meta == b._meta:
|
|
108
106
|
return f(a._data, b._data)
|
|
109
107
|
raise MetadataError(f, a, b, error='unequal') from None
|
|
110
|
-
if isinstance(a,
|
|
108
|
+
if isinstance(a, Quantity):
|
|
111
109
|
if not a._meta:
|
|
112
110
|
return f(a._data, b)
|
|
113
111
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
114
|
-
if isinstance(b,
|
|
112
|
+
if isinstance(b, Quantity):
|
|
115
113
|
if not b._meta:
|
|
116
114
|
return f(a, b._data)
|
|
117
115
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
@@ -120,15 +118,15 @@ def ordering(f: operators.Operator, a, b):
|
|
|
120
118
|
|
|
121
119
|
def additive(f: operators.Operator, a, b):
|
|
122
120
|
"""Compute the additive operation f(a, b)."""
|
|
123
|
-
if isinstance(a,
|
|
121
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
124
122
|
if a._meta == b._meta:
|
|
125
123
|
return type(a)(f(a._data, b._data), **a._meta)
|
|
126
124
|
raise MetadataError(f, a, b, error='unequal') from None
|
|
127
|
-
if isinstance(a,
|
|
125
|
+
if isinstance(a, Quantity):
|
|
128
126
|
if not a._meta:
|
|
129
127
|
return type(a)(f(a._data, b))
|
|
130
128
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
131
|
-
if isinstance(b,
|
|
129
|
+
if isinstance(b, Quantity):
|
|
132
130
|
if not b._meta:
|
|
133
131
|
return type(b)(f(a, b._data))
|
|
134
132
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
@@ -137,7 +135,7 @@ def additive(f: operators.Operator, a, b):
|
|
|
137
135
|
|
|
138
136
|
def multiplicative(f: operators.Operator, a, b):
|
|
139
137
|
"""Compute the multiplicative operation f(a, b)."""
|
|
140
|
-
if isinstance(a,
|
|
138
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
141
139
|
keys = set(a._meta) & set(b._meta)
|
|
142
140
|
meta = {}
|
|
143
141
|
for key in keys:
|
|
@@ -154,7 +152,7 @@ def multiplicative(f: operators.Operator, a, b):
|
|
|
154
152
|
if key not in keys:
|
|
155
153
|
meta[key] = value
|
|
156
154
|
return type(a)(f(a._data, b._data), **meta)
|
|
157
|
-
if isinstance(a,
|
|
155
|
+
if isinstance(a, Quantity):
|
|
158
156
|
meta = {}
|
|
159
157
|
for key, value in a._meta.items():
|
|
160
158
|
try:
|
|
@@ -164,7 +162,7 @@ def multiplicative(f: operators.Operator, a, b):
|
|
|
164
162
|
else:
|
|
165
163
|
meta[key] = v
|
|
166
164
|
return type(a)(f(a._data, b), **meta)
|
|
167
|
-
if isinstance(b,
|
|
165
|
+
if isinstance(b, Quantity):
|
|
168
166
|
meta = {}
|
|
169
167
|
for key, value in b._meta.items():
|
|
170
168
|
try:
|
oprattr/abstract.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import collections.abc
|
|
2
|
+
import numbers
|
|
3
|
+
|
|
4
|
+
import numerical
|
|
5
|
+
import numpy.typing
|
|
6
|
+
|
|
7
|
+
from . import typeface
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
DataType = typeface.TypeVar(
|
|
11
|
+
'DataType',
|
|
12
|
+
int,
|
|
13
|
+
float,
|
|
14
|
+
numbers.Number,
|
|
15
|
+
numpy.number,
|
|
16
|
+
numpy.typing.ArrayLike,
|
|
17
|
+
numpy.typing.NDArray,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@typeface.runtime_checkable
|
|
22
|
+
class Quantity(numerical.Quantity[DataType], typeface.Protocol):
|
|
23
|
+
"""Protocol for numerical objects with metadata."""
|
|
24
|
+
|
|
25
|
+
_meta: collections.abc.Mapping[str, typeface.Any]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Object(numerical.Real, typeface.Generic[DataType]):
|
|
29
|
+
"""A real-valued object with metadata attributes."""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
__data: DataType,
|
|
34
|
+
**metadata,
|
|
35
|
+
) -> None:
|
|
36
|
+
if not isinstance(__data, numerical.Real):
|
|
37
|
+
raise TypeError("Data input to Object must be real-valued")
|
|
38
|
+
self._data = __data
|
|
39
|
+
self._meta = metadata
|
|
40
|
+
|
|
41
|
+
def __repr__(self):
|
|
42
|
+
"""Called for repr(self)."""
|
|
43
|
+
try:
|
|
44
|
+
datastr = numpy.array2string(
|
|
45
|
+
self._data,
|
|
46
|
+
separator=", ",
|
|
47
|
+
threshold=6,
|
|
48
|
+
edgeitems=2,
|
|
49
|
+
prefix=f"{self.__class__.__qualname__}(",
|
|
50
|
+
suffix=")"
|
|
51
|
+
)
|
|
52
|
+
except Exception:
|
|
53
|
+
datastr = str(self._data)
|
|
54
|
+
metastr = "metadata={" + ", ".join(f"{k!r}" for k in self._meta) + "}"
|
|
55
|
+
return f"{self.__class__.__qualname__}({datastr}, {metastr})"
|
|
56
|
+
|
oprattr/mixins.py
CHANGED
|
@@ -1,15 +1,89 @@
|
|
|
1
|
+
import collections.abc
|
|
1
2
|
import numbers
|
|
2
|
-
import typing
|
|
3
3
|
|
|
4
4
|
import numpy
|
|
5
5
|
|
|
6
|
-
from . import
|
|
6
|
+
from . import abstract
|
|
7
|
+
from . import typeface
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
T =
|
|
10
|
+
T = typeface.TypeVar('T')
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
class Real:
|
|
14
|
+
"""Mixin for adding basic real-valued operator support."""
|
|
15
|
+
|
|
16
|
+
def __abs__(self):
|
|
17
|
+
return self
|
|
18
|
+
|
|
19
|
+
def __pos__(self):
|
|
20
|
+
return self
|
|
21
|
+
|
|
22
|
+
def __neg__(self):
|
|
23
|
+
return self
|
|
24
|
+
|
|
25
|
+
def __eq__(self, other):
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
def __ne__(self, other):
|
|
29
|
+
return not (self == other)
|
|
30
|
+
|
|
31
|
+
def __lt__(self, other):
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
def __le__(self, other):
|
|
35
|
+
return (self < other) and (self == other)
|
|
36
|
+
|
|
37
|
+
def __gt__(self, other):
|
|
38
|
+
return not (self <= other)
|
|
39
|
+
|
|
40
|
+
def __ge__(self, other):
|
|
41
|
+
return not (self < other)
|
|
42
|
+
|
|
43
|
+
def __add__(self, other):
|
|
44
|
+
return self
|
|
45
|
+
|
|
46
|
+
def __radd__(self, other):
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def __sub__(self, other):
|
|
50
|
+
return self
|
|
51
|
+
|
|
52
|
+
def __rsub__(self, other):
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def __mul__(self, other):
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
def __rmul__(self, other):
|
|
59
|
+
return self
|
|
60
|
+
|
|
61
|
+
def __truediv__(self, other):
|
|
62
|
+
return self
|
|
63
|
+
|
|
64
|
+
def __rtruediv__(self, other):
|
|
65
|
+
return self
|
|
66
|
+
|
|
67
|
+
def __floordiv__(self, other):
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
def __rfloordiv__(self, other):
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
def __mod__(self, other):
|
|
74
|
+
return self
|
|
75
|
+
|
|
76
|
+
def __rmod__(self, other):
|
|
77
|
+
return self
|
|
78
|
+
|
|
79
|
+
def __pow__(self, other):
|
|
80
|
+
return self
|
|
81
|
+
|
|
82
|
+
def __rpow__(self, other):
|
|
83
|
+
return self
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
UserFunction = collections.abc.Callable[..., T]
|
|
13
87
|
|
|
14
88
|
|
|
15
89
|
class Numpy:
|
|
@@ -54,7 +128,7 @@ class Numpy:
|
|
|
54
128
|
numpy.ndarray,
|
|
55
129
|
numbers.Number,
|
|
56
130
|
list,
|
|
57
|
-
|
|
131
|
+
abstract.Quantity,
|
|
58
132
|
}
|
|
59
133
|
|
|
60
134
|
def __array_ufunc__(self, ufunc, method, *args, **kwargs):
|
|
@@ -89,7 +163,7 @@ class Numpy:
|
|
|
89
163
|
return NotImplemented
|
|
90
164
|
if out:
|
|
91
165
|
kwargs['out'] = tuple(
|
|
92
|
-
x._data if isinstance(x,
|
|
166
|
+
x._data if isinstance(x, abstract.Quantity)
|
|
93
167
|
else x for x in out
|
|
94
168
|
)
|
|
95
169
|
if self._implements(ufunc):
|
|
@@ -134,7 +208,7 @@ class Numpy:
|
|
|
134
208
|
|
|
135
209
|
_FUNCTION_TYPES = {
|
|
136
210
|
numpy.ndarray,
|
|
137
|
-
|
|
211
|
+
abstract.Object,
|
|
138
212
|
} | set(numpy.ScalarType)
|
|
139
213
|
|
|
140
214
|
def __array_function__(self, func, types, args, kwargs):
|
|
@@ -212,7 +286,7 @@ class Numpy:
|
|
|
212
286
|
types = self._get_numpy_types(types)
|
|
213
287
|
return array.__array_function__(func, types, args, kwargs)
|
|
214
288
|
|
|
215
|
-
def _get_numpy_array(self) ->
|
|
289
|
+
def _get_numpy_array(self) -> numpy.typing.NDArray | None:
|
|
216
290
|
"""Convert the data interface to an array for `numpy` mixin methods.
|
|
217
291
|
|
|
218
292
|
Notes
|
|
@@ -251,7 +325,7 @@ class Numpy:
|
|
|
251
325
|
`arg` if `arg` is an instance of the base object class; otherwise, it
|
|
252
326
|
will return the unmodified argument.
|
|
253
327
|
"""
|
|
254
|
-
if isinstance(arg,
|
|
328
|
+
if isinstance(arg, abstract.Quantity):
|
|
255
329
|
return arg._data
|
|
256
330
|
return arg
|
|
257
331
|
|
|
@@ -267,11 +341,11 @@ class Numpy:
|
|
|
267
341
|
"""
|
|
268
342
|
return tuple(
|
|
269
343
|
ti for ti in types
|
|
270
|
-
if not issubclass(ti,
|
|
344
|
+
if not issubclass(ti, abstract.Object)
|
|
271
345
|
)
|
|
272
346
|
|
|
273
347
|
@classmethod
|
|
274
|
-
def _implements(cls, operation:
|
|
348
|
+
def _implements(cls, operation: collections.abc.Callable):
|
|
275
349
|
"""True if this class defines a custom implementation for `operation`.
|
|
276
350
|
|
|
277
351
|
This is a helper methods that gracefully handles the case in which a
|
|
@@ -283,11 +357,11 @@ class Numpy:
|
|
|
283
357
|
return False
|
|
284
358
|
return result
|
|
285
359
|
|
|
286
|
-
_FUNCTIONS:
|
|
360
|
+
_FUNCTIONS: dict[str, collections.abc.Callable]=None
|
|
287
361
|
"""Internal collection of custom `numpy` function implementations."""
|
|
288
362
|
|
|
289
363
|
@classmethod
|
|
290
|
-
def implementation(cls, numpy_function:
|
|
364
|
+
def implementation(cls, numpy_function: collections.abc.Callable, /):
|
|
291
365
|
"""Register a custom implementation of this `numpy` function.
|
|
292
366
|
|
|
293
367
|
Parameters
|
|
@@ -351,7 +425,7 @@ class Numpy:
|
|
|
351
425
|
@classmethod
|
|
352
426
|
def implement(
|
|
353
427
|
cls,
|
|
354
|
-
numpy_function:
|
|
428
|
+
numpy_function: collections.abc.Callable,
|
|
355
429
|
user_function: UserFunction,
|
|
356
430
|
/,
|
|
357
431
|
) -> None:
|
oprattr/operators.py
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
A namespace for operators used by this package's `Object` class.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import collections.abc
|
|
5
6
|
import builtins
|
|
6
7
|
import operator
|
|
7
|
-
import typing
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Operator:
|
|
11
11
|
"""Base class for enhanced operators."""
|
|
12
|
-
def __init__(self, __f:
|
|
12
|
+
def __init__(self, __f: collections.abc.Callable, operation: str):
|
|
13
13
|
self._f = __f
|
|
14
14
|
self._operation = operation
|
|
15
15
|
|
oprattr/typeface.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Support for type annotations.
|
|
3
|
+
|
|
4
|
+
This module provides a single interface to type annotations, including those
|
|
5
|
+
that are not defined by the operative Python version and those that this package
|
|
6
|
+
prefers to use from future versions.
|
|
7
|
+
|
|
8
|
+
Examples
|
|
9
|
+
--------
|
|
10
|
+
* Suppose `BestType` is available in the `typing` module starting with Python
|
|
11
|
+
version 3.X and is available in the `typing_extensions` module for earlier
|
|
12
|
+
versions. If the user is running with Python version <3.X, this module will
|
|
13
|
+
import `BestType` from `typing_extensions`. Otherwise, it will import
|
|
14
|
+
`BestType` from `typing`.
|
|
15
|
+
* Support `UpdatedType` is available in the `typing` module for the user's
|
|
16
|
+
version of Python, but this package wishes to take advantage of updates since
|
|
17
|
+
that version. This module will automatically import the version from
|
|
18
|
+
`typing_extensions`.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import typing
|
|
22
|
+
import typing_extensions
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
__all__ = ()
|
|
26
|
+
|
|
27
|
+
EXTENDED = [
|
|
28
|
+
'Protocol',
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
def __getattr__(name: str) -> type:
|
|
32
|
+
"""Get a built-in type annotation."""
|
|
33
|
+
if name in EXTENDED:
|
|
34
|
+
return getattr(typing_extensions, name)
|
|
35
|
+
try:
|
|
36
|
+
attr = getattr(typing, name)
|
|
37
|
+
except AttributeError:
|
|
38
|
+
attr = getattr(typing_extensions, name)
|
|
39
|
+
return attr
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
oprattr/typeface.pyi
ADDED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oprattr
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Author-email: Matthew Young <myoung.space.science@gmail.com>
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: numerical
|
|
7
9
|
Requires-Dist: numpy>=2.2.1
|
|
8
10
|
Requires-Dist: scipy>=1.15.0
|
|
9
11
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
oprattr/__init__.py,sha256=eo0zjBDcrDG-Ymeqm-k6lfq18aqCLvgi9ipHNu7wkQg,5591
|
|
2
|
+
oprattr/_operations.py,sha256=GwoZjjs-rcX70SuNBAiu-ja9P5dBRAJ0NTfMLQWY6yY,5824
|
|
3
|
+
oprattr/abstract.py,sha256=I3AYc8F79IMgH2esaKSvCTFelV_jFxWRuvXDuTZ8E94,1407
|
|
4
|
+
oprattr/mixins.py,sha256=_qqhReZu9Ta83irVihUrhggcObEj4lyp-3_S9K2hEog,16875
|
|
5
|
+
oprattr/operators.py,sha256=0ix9xHYujJZoUp4mBy1Oar_z17nUlZ8EoKU9KqpaAe0,1172
|
|
6
|
+
oprattr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
oprattr/typeface.py,sha256=FPGAdTZUmS_jd56PcZ5tCcUE_rXNubINBpVMQLRenvg,1214
|
|
8
|
+
oprattr/typeface.pyi,sha256=6gVdlDXtwl6Qyv07JWuRhM78VTGzds0pJ2KZUAAGcXs,113
|
|
9
|
+
oprattr-0.3.0.dist-info/METADATA,sha256=a-xInHgyeHOBNhKU1tnnftszWZ8vLumwgeLCYA_Z6-Y,375
|
|
10
|
+
oprattr-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
oprattr-0.3.0.dist-info/licenses/LICENSE,sha256=m2oXG0JDq5RzaKTS57TvGyNq5cWcV4_nfmLZjzLdYTg,1513
|
|
12
|
+
oprattr-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
BSD 3-Clause License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2025, Matt Young
|
|
6
|
+
All rights reserved.
|
|
7
|
+
|
|
8
|
+
Redistribution and use in source and binary forms, with or without
|
|
9
|
+
modification, are permitted provided that the following conditions are met:
|
|
10
|
+
|
|
11
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
12
|
+
list of conditions and the following disclaimer.
|
|
13
|
+
|
|
14
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
15
|
+
this list of conditions and the following disclaimer in the documentation
|
|
16
|
+
and/or other materials provided with the distribution.
|
|
17
|
+
|
|
18
|
+
* Neither the name of the copyright holder nor the names of its
|
|
19
|
+
contributors may be used to endorse or promote products derived from
|
|
20
|
+
this software without specific prior written permission.
|
|
21
|
+
|
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
25
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
26
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
27
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
28
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
29
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
30
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
|
oprattr/_types.py
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import numbers
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
|
-
import numpy.typing
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@typing.runtime_checkable
|
|
9
|
-
class Real(typing.Protocol):
|
|
10
|
-
"""Abstract protocol for real-valued objects."""
|
|
11
|
-
|
|
12
|
-
@abc.abstractmethod
|
|
13
|
-
def __abs__(self):
|
|
14
|
-
return NotImplemented
|
|
15
|
-
|
|
16
|
-
@abc.abstractmethod
|
|
17
|
-
def __pos__(self):
|
|
18
|
-
return NotImplemented
|
|
19
|
-
|
|
20
|
-
@abc.abstractmethod
|
|
21
|
-
def __neg__(self):
|
|
22
|
-
return NotImplemented
|
|
23
|
-
|
|
24
|
-
@abc.abstractmethod
|
|
25
|
-
def __eq__(self, other):
|
|
26
|
-
return False
|
|
27
|
-
|
|
28
|
-
@abc.abstractmethod
|
|
29
|
-
def __ne__(self, other):
|
|
30
|
-
return True
|
|
31
|
-
|
|
32
|
-
@abc.abstractmethod
|
|
33
|
-
def __le__(self, other):
|
|
34
|
-
return NotImplemented
|
|
35
|
-
|
|
36
|
-
@abc.abstractmethod
|
|
37
|
-
def __lt__(self, other):
|
|
38
|
-
return NotImplemented
|
|
39
|
-
|
|
40
|
-
@abc.abstractmethod
|
|
41
|
-
def __ge__(self, other):
|
|
42
|
-
return NotImplemented
|
|
43
|
-
|
|
44
|
-
@abc.abstractmethod
|
|
45
|
-
def __gt__(self, other):
|
|
46
|
-
return NotImplemented
|
|
47
|
-
|
|
48
|
-
@abc.abstractmethod
|
|
49
|
-
def __add__(self, other):
|
|
50
|
-
return NotImplemented
|
|
51
|
-
|
|
52
|
-
@abc.abstractmethod
|
|
53
|
-
def __radd__(self, other):
|
|
54
|
-
return NotImplemented
|
|
55
|
-
|
|
56
|
-
@abc.abstractmethod
|
|
57
|
-
def __sub__(self, other):
|
|
58
|
-
return NotImplemented
|
|
59
|
-
|
|
60
|
-
@abc.abstractmethod
|
|
61
|
-
def __rsub__(self, other):
|
|
62
|
-
return NotImplemented
|
|
63
|
-
|
|
64
|
-
@abc.abstractmethod
|
|
65
|
-
def __mul__(self, other):
|
|
66
|
-
return NotImplemented
|
|
67
|
-
|
|
68
|
-
@abc.abstractmethod
|
|
69
|
-
def __rmul__(self, other):
|
|
70
|
-
return NotImplemented
|
|
71
|
-
|
|
72
|
-
@abc.abstractmethod
|
|
73
|
-
def __truediv__(self, other):
|
|
74
|
-
return NotImplemented
|
|
75
|
-
|
|
76
|
-
@abc.abstractmethod
|
|
77
|
-
def __rtruediv__(self, other):
|
|
78
|
-
return NotImplemented
|
|
79
|
-
|
|
80
|
-
@abc.abstractmethod
|
|
81
|
-
def __floordiv__(self, other):
|
|
82
|
-
return NotImplemented
|
|
83
|
-
|
|
84
|
-
@abc.abstractmethod
|
|
85
|
-
def __rfloordiv__(self, other):
|
|
86
|
-
return NotImplemented
|
|
87
|
-
|
|
88
|
-
@abc.abstractmethod
|
|
89
|
-
def __mod__(self, other):
|
|
90
|
-
return NotImplemented
|
|
91
|
-
|
|
92
|
-
@abc.abstractmethod
|
|
93
|
-
def __rmod__(self, other):
|
|
94
|
-
return NotImplemented
|
|
95
|
-
|
|
96
|
-
@abc.abstractmethod
|
|
97
|
-
def __pow__(self, other):
|
|
98
|
-
return NotImplemented
|
|
99
|
-
|
|
100
|
-
@abc.abstractmethod
|
|
101
|
-
def __rpow__(self, other):
|
|
102
|
-
return NotImplemented
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
DataType = typing.TypeVar(
|
|
106
|
-
'DataType',
|
|
107
|
-
int,
|
|
108
|
-
float,
|
|
109
|
-
numbers.Number,
|
|
110
|
-
numpy.number,
|
|
111
|
-
numpy.typing.ArrayLike,
|
|
112
|
-
numpy.typing.NDArray,
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
class Object(Real, typing.Generic[DataType]):
|
|
117
|
-
"""A real-valued object with metadata attributes."""
|
|
118
|
-
|
|
119
|
-
def __init__(
|
|
120
|
-
self,
|
|
121
|
-
__data: DataType,
|
|
122
|
-
**metadata,
|
|
123
|
-
) -> None:
|
|
124
|
-
if not isinstance(__data, Real):
|
|
125
|
-
raise TypeError("Data input to Object must be real-valued")
|
|
126
|
-
self._data = __data
|
|
127
|
-
self._meta = metadata
|
|
128
|
-
|
|
129
|
-
def __repr__(self):
|
|
130
|
-
"""Called for repr(self)."""
|
|
131
|
-
try:
|
|
132
|
-
datastr = numpy.array2string(
|
|
133
|
-
self._data,
|
|
134
|
-
separator=", ",
|
|
135
|
-
threshold=6,
|
|
136
|
-
edgeitems=2,
|
|
137
|
-
prefix=f"{self.__class__.__qualname__}(",
|
|
138
|
-
suffix=")"
|
|
139
|
-
)
|
|
140
|
-
except Exception:
|
|
141
|
-
datastr = str(self._data)
|
|
142
|
-
metastr = "metadata={" + ", ".join(f"{k!r}" for k in self._meta) + "}"
|
|
143
|
-
return f"{self.__class__.__qualname__}({datastr}, {metastr})"
|
|
144
|
-
|
oprattr-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
oprattr/__init__.py,sha256=_mEw0H7v3bpKXFPvM_koOVnvsUQLO3HK6zBmnKCOFQU,5553
|
|
2
|
-
oprattr/_operations.py,sha256=e8kTjc183mKR51EX2Ds22kPx0dQc5uqct2btgHzCgoY,5829
|
|
3
|
-
oprattr/_types.py,sha256=TzTt9GkQ5KZc5kqajdLnn8EcvxzMj3SALSI5iJrB6Vk,3182
|
|
4
|
-
oprattr/mixins.py,sha256=G-4aVbQ1wLDz15KSFL9yWqlU5HXQFwp4g7VoFjl7_24,15471
|
|
5
|
-
oprattr/operators.py,sha256=skqQpIezGSDbsmB2h-UNnxG_7aDGT6PsnvUkondpwOg,1154
|
|
6
|
-
oprattr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
oprattr-0.1.0.dist-info/METADATA,sha256=nwgndllGe5R1KX3UGxZjzvVcpdPG7jg9NQJDO8LtQhI,328
|
|
8
|
-
oprattr-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
-
oprattr-0.1.0.dist-info/RECORD,,
|
|
File without changes
|