oprattr 0.2.0__py3-none-any.whl → 0.4.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 +16 -6
- oprattr/_operations.py +38 -29
- oprattr/abstract.py +13 -101
- oprattr/mixins.py +12 -11
- oprattr/typeface.py +42 -0
- oprattr/typeface.pyi +5 -0
- {oprattr-0.2.0.dist-info → oprattr-0.4.0.dist-info}/METADATA +3 -1
- oprattr-0.4.0.dist-info/RECORD +11 -0
- oprattr-0.4.0.dist-info/licenses/LICENSE +32 -0
- oprattr/operators.py +0 -41
- oprattr-0.2.0.dist-info/RECORD +0 -9
- {oprattr-0.2.0.dist-info → oprattr-0.4.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
|
+
from numerical import operators
|
|
5
6
|
import numpy
|
|
6
7
|
|
|
7
|
-
from . import mixins
|
|
8
|
-
from . import operators
|
|
9
8
|
from . import abstract
|
|
9
|
+
from . import mixins
|
|
10
|
+
from . import typeface
|
|
10
11
|
from ._operations import (
|
|
11
12
|
unary,
|
|
12
13
|
equality,
|
|
@@ -16,7 +17,7 @@ from ._operations import (
|
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
T =
|
|
20
|
+
T = typeface.TypeVar('T')
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class Operand(abstract.Object[T], mixins.Numpy):
|
|
@@ -114,12 +115,21 @@ class Operand(abstract.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)."""
|
|
121
122
|
return numpy.array(self._data, *args, **kwargs)
|
|
122
123
|
|
|
124
|
+
def _apply_ufunc(self, ufunc, method, *args, **kwargs):
|
|
125
|
+
if ufunc in (numpy.equal, numpy.not_equal):
|
|
126
|
+
# NOTE: We are probably here because the left operand is a
|
|
127
|
+
# `numpy.ndarray`, which would otherwise take control and return the
|
|
128
|
+
# pure `numpy` result.
|
|
129
|
+
f = getattr(ufunc, method)
|
|
130
|
+
return equality(f, *args)
|
|
131
|
+
return super()._apply_ufunc(ufunc, method, *args, **kwargs)
|
|
132
|
+
|
|
123
133
|
|
|
124
134
|
@Operand.implementation(numpy.array_equal)
|
|
125
135
|
def array_equal(
|
|
@@ -155,7 +165,7 @@ def gradient(x: Operand[T], *args, **kwargs):
|
|
|
155
165
|
return type(x)(data, **meta)
|
|
156
166
|
|
|
157
167
|
|
|
158
|
-
def wrapnumpy(f:
|
|
168
|
+
def wrapnumpy(f: collections.abc.Callable):
|
|
159
169
|
"""Implement a numpy function for objects with metadata."""
|
|
160
170
|
@functools.wraps(f)
|
|
161
171
|
def method(x: Operand[T], **kwargs):
|
oprattr/_operations.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
from numerical import operators
|
|
2
2
|
|
|
3
|
-
from . import
|
|
4
|
-
from .abstract import Object
|
|
3
|
+
from .abstract import Quantity
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
class MetadataError(TypeError):
|
|
@@ -11,8 +10,8 @@ class MetadataError(TypeError):
|
|
|
11
10
|
self,
|
|
12
11
|
f: operators.Operator,
|
|
13
12
|
*args,
|
|
14
|
-
error:
|
|
15
|
-
key:
|
|
13
|
+
error: str | None = None,
|
|
14
|
+
key: str | None = None,
|
|
16
15
|
) -> None:
|
|
17
16
|
super().__init__(*args)
|
|
18
17
|
self._f = f
|
|
@@ -33,8 +32,8 @@ class MetadataError(TypeError):
|
|
|
33
32
|
def _build_error_message(
|
|
34
33
|
f: operators.Operator,
|
|
35
34
|
*types: type,
|
|
36
|
-
error:
|
|
37
|
-
key:
|
|
35
|
+
error: str | None = None,
|
|
36
|
+
key: str | None = None,
|
|
38
37
|
) -> str:
|
|
39
38
|
"""Helper for `_raise_metadata_exception`.
|
|
40
39
|
|
|
@@ -50,9 +49,9 @@ def _build_error_message(
|
|
|
50
49
|
if len(types) == 2:
|
|
51
50
|
a, b = types
|
|
52
51
|
endstr = "because {} has metadata"
|
|
53
|
-
if issubclass(a,
|
|
52
|
+
if issubclass(a, Quantity):
|
|
54
53
|
return f"{errmsg} between {a} and {b} {endstr.format(str(a))}"
|
|
55
|
-
if issubclass(b,
|
|
54
|
+
if issubclass(b, Quantity):
|
|
56
55
|
return f"{errmsg} between {a} and {b} {endstr.format(str(b))}"
|
|
57
56
|
if errstr == 'type':
|
|
58
57
|
if key is None:
|
|
@@ -71,7 +70,7 @@ def _build_error_message(
|
|
|
71
70
|
|
|
72
71
|
def unary(f: operators.Operator, a):
|
|
73
72
|
"""Compute the unary operation f(a)."""
|
|
74
|
-
if isinstance(a,
|
|
73
|
+
if isinstance(a, Quantity):
|
|
75
74
|
meta = {}
|
|
76
75
|
for key, value in a._meta.items():
|
|
77
76
|
try:
|
|
@@ -86,32 +85,42 @@ def unary(f: operators.Operator, a):
|
|
|
86
85
|
|
|
87
86
|
def equality(f: operators.Operator, a, b):
|
|
88
87
|
"""Compute the equality operation f(a, b)."""
|
|
89
|
-
if isinstance(a,
|
|
88
|
+
x = a._data if isinstance(a, Quantity) else a
|
|
89
|
+
y = b._data if isinstance(b, Quantity) else b
|
|
90
|
+
fxy = f(x, y)
|
|
91
|
+
try:
|
|
92
|
+
iter(fxy)
|
|
93
|
+
except TypeError:
|
|
94
|
+
r = bool(fxy)
|
|
95
|
+
else:
|
|
96
|
+
r = all(fxy)
|
|
97
|
+
isne = f(1, 2)
|
|
98
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
90
99
|
if a._meta != b._meta:
|
|
91
|
-
return
|
|
92
|
-
return
|
|
93
|
-
if isinstance(a,
|
|
100
|
+
return isne
|
|
101
|
+
return r
|
|
102
|
+
if isinstance(a, Quantity):
|
|
94
103
|
if not a._meta:
|
|
95
|
-
return
|
|
96
|
-
return
|
|
97
|
-
if isinstance(b,
|
|
104
|
+
return r
|
|
105
|
+
return isne
|
|
106
|
+
if isinstance(b, Quantity):
|
|
98
107
|
if not b._meta:
|
|
99
|
-
return
|
|
100
|
-
return
|
|
101
|
-
return
|
|
108
|
+
return r
|
|
109
|
+
return isne
|
|
110
|
+
return r
|
|
102
111
|
|
|
103
112
|
|
|
104
113
|
def ordering(f: operators.Operator, a, b):
|
|
105
114
|
"""Compute the ordering operation f(a, b)."""
|
|
106
|
-
if isinstance(a,
|
|
115
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
107
116
|
if a._meta == b._meta:
|
|
108
117
|
return f(a._data, b._data)
|
|
109
118
|
raise MetadataError(f, a, b, error='unequal') from None
|
|
110
|
-
if isinstance(a,
|
|
119
|
+
if isinstance(a, Quantity):
|
|
111
120
|
if not a._meta:
|
|
112
121
|
return f(a._data, b)
|
|
113
122
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
114
|
-
if isinstance(b,
|
|
123
|
+
if isinstance(b, Quantity):
|
|
115
124
|
if not b._meta:
|
|
116
125
|
return f(a, b._data)
|
|
117
126
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
@@ -120,15 +129,15 @@ def ordering(f: operators.Operator, a, b):
|
|
|
120
129
|
|
|
121
130
|
def additive(f: operators.Operator, a, b):
|
|
122
131
|
"""Compute the additive operation f(a, b)."""
|
|
123
|
-
if isinstance(a,
|
|
132
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
124
133
|
if a._meta == b._meta:
|
|
125
134
|
return type(a)(f(a._data, b._data), **a._meta)
|
|
126
135
|
raise MetadataError(f, a, b, error='unequal') from None
|
|
127
|
-
if isinstance(a,
|
|
136
|
+
if isinstance(a, Quantity):
|
|
128
137
|
if not a._meta:
|
|
129
138
|
return type(a)(f(a._data, b))
|
|
130
139
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
131
|
-
if isinstance(b,
|
|
140
|
+
if isinstance(b, Quantity):
|
|
132
141
|
if not b._meta:
|
|
133
142
|
return type(b)(f(a, b._data))
|
|
134
143
|
raise MetadataError(f, a, b, error='non-empty') from None
|
|
@@ -137,7 +146,7 @@ def additive(f: operators.Operator, a, b):
|
|
|
137
146
|
|
|
138
147
|
def multiplicative(f: operators.Operator, a, b):
|
|
139
148
|
"""Compute the multiplicative operation f(a, b)."""
|
|
140
|
-
if isinstance(a,
|
|
149
|
+
if isinstance(a, Quantity) and isinstance(b, Quantity):
|
|
141
150
|
keys = set(a._meta) & set(b._meta)
|
|
142
151
|
meta = {}
|
|
143
152
|
for key in keys:
|
|
@@ -154,7 +163,7 @@ def multiplicative(f: operators.Operator, a, b):
|
|
|
154
163
|
if key not in keys:
|
|
155
164
|
meta[key] = value
|
|
156
165
|
return type(a)(f(a._data, b._data), **meta)
|
|
157
|
-
if isinstance(a,
|
|
166
|
+
if isinstance(a, Quantity):
|
|
158
167
|
meta = {}
|
|
159
168
|
for key, value in a._meta.items():
|
|
160
169
|
try:
|
|
@@ -164,7 +173,7 @@ def multiplicative(f: operators.Operator, a, b):
|
|
|
164
173
|
else:
|
|
165
174
|
meta[key] = v
|
|
166
175
|
return type(a)(f(a._data, b), **meta)
|
|
167
|
-
if isinstance(b,
|
|
176
|
+
if isinstance(b, Quantity):
|
|
168
177
|
meta = {}
|
|
169
178
|
for key, value in b._meta.items():
|
|
170
179
|
try:
|
oprattr/abstract.py
CHANGED
|
@@ -1,108 +1,13 @@
|
|
|
1
|
-
import abc
|
|
1
|
+
import collections.abc
|
|
2
2
|
import numbers
|
|
3
|
-
import typing
|
|
4
3
|
|
|
4
|
+
import numerical
|
|
5
5
|
import numpy.typing
|
|
6
6
|
|
|
7
|
+
from . import typeface
|
|
7
8
|
|
|
8
|
-
@typing.runtime_checkable
|
|
9
|
-
class Real(typing.Protocol):
|
|
10
|
-
"""Abstract protocol for real-valued objects."""
|
|
11
9
|
|
|
12
|
-
|
|
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(
|
|
10
|
+
DataType = typeface.TypeVar(
|
|
106
11
|
'DataType',
|
|
107
12
|
int,
|
|
108
13
|
float,
|
|
@@ -113,7 +18,14 @@ DataType = typing.TypeVar(
|
|
|
113
18
|
)
|
|
114
19
|
|
|
115
20
|
|
|
116
|
-
|
|
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]):
|
|
117
29
|
"""A real-valued object with metadata attributes."""
|
|
118
30
|
|
|
119
31
|
def __init__(
|
|
@@ -121,7 +33,7 @@ class Object(Real, typing.Generic[DataType]):
|
|
|
121
33
|
__data: DataType,
|
|
122
34
|
**metadata,
|
|
123
35
|
) -> None:
|
|
124
|
-
if not isinstance(__data, Real):
|
|
36
|
+
if not isinstance(__data, numerical.Real):
|
|
125
37
|
raise TypeError("Data input to Object must be real-valued")
|
|
126
38
|
self._data = __data
|
|
127
39
|
self._meta = metadata
|
oprattr/mixins.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import collections.abc
|
|
1
2
|
import numbers
|
|
2
|
-
import typing
|
|
3
3
|
|
|
4
4
|
import numpy
|
|
5
5
|
|
|
6
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:
|
|
@@ -82,7 +83,7 @@ class Real:
|
|
|
82
83
|
return self
|
|
83
84
|
|
|
84
85
|
|
|
85
|
-
UserFunction =
|
|
86
|
+
UserFunction = collections.abc.Callable[..., T]
|
|
86
87
|
|
|
87
88
|
|
|
88
89
|
class Numpy:
|
|
@@ -127,7 +128,7 @@ class Numpy:
|
|
|
127
128
|
numpy.ndarray,
|
|
128
129
|
numbers.Number,
|
|
129
130
|
list,
|
|
130
|
-
abstract.
|
|
131
|
+
abstract.Quantity,
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
def __array_ufunc__(self, ufunc, method, *args, **kwargs):
|
|
@@ -162,7 +163,7 @@ class Numpy:
|
|
|
162
163
|
return NotImplemented
|
|
163
164
|
if out:
|
|
164
165
|
kwargs['out'] = tuple(
|
|
165
|
-
x._data if isinstance(x, abstract.
|
|
166
|
+
x._data if isinstance(x, abstract.Quantity)
|
|
166
167
|
else x for x in out
|
|
167
168
|
)
|
|
168
169
|
if self._implements(ufunc):
|
|
@@ -285,7 +286,7 @@ class Numpy:
|
|
|
285
286
|
types = self._get_numpy_types(types)
|
|
286
287
|
return array.__array_function__(func, types, args, kwargs)
|
|
287
288
|
|
|
288
|
-
def _get_numpy_array(self) ->
|
|
289
|
+
def _get_numpy_array(self) -> numpy.typing.NDArray | None:
|
|
289
290
|
"""Convert the data interface to an array for `numpy` mixin methods.
|
|
290
291
|
|
|
291
292
|
Notes
|
|
@@ -324,7 +325,7 @@ class Numpy:
|
|
|
324
325
|
`arg` if `arg` is an instance of the base object class; otherwise, it
|
|
325
326
|
will return the unmodified argument.
|
|
326
327
|
"""
|
|
327
|
-
if isinstance(arg, abstract.
|
|
328
|
+
if isinstance(arg, abstract.Quantity):
|
|
328
329
|
return arg._data
|
|
329
330
|
return arg
|
|
330
331
|
|
|
@@ -344,7 +345,7 @@ class Numpy:
|
|
|
344
345
|
)
|
|
345
346
|
|
|
346
347
|
@classmethod
|
|
347
|
-
def _implements(cls, operation:
|
|
348
|
+
def _implements(cls, operation: collections.abc.Callable):
|
|
348
349
|
"""True if this class defines a custom implementation for `operation`.
|
|
349
350
|
|
|
350
351
|
This is a helper methods that gracefully handles the case in which a
|
|
@@ -356,11 +357,11 @@ class Numpy:
|
|
|
356
357
|
return False
|
|
357
358
|
return result
|
|
358
359
|
|
|
359
|
-
_FUNCTIONS:
|
|
360
|
+
_FUNCTIONS: dict[str, collections.abc.Callable]=None
|
|
360
361
|
"""Internal collection of custom `numpy` function implementations."""
|
|
361
362
|
|
|
362
363
|
@classmethod
|
|
363
|
-
def implementation(cls, numpy_function:
|
|
364
|
+
def implementation(cls, numpy_function: collections.abc.Callable, /):
|
|
364
365
|
"""Register a custom implementation of this `numpy` function.
|
|
365
366
|
|
|
366
367
|
Parameters
|
|
@@ -424,7 +425,7 @@ class Numpy:
|
|
|
424
425
|
@classmethod
|
|
425
426
|
def implement(
|
|
426
427
|
cls,
|
|
427
|
-
numpy_function:
|
|
428
|
+
numpy_function: collections.abc.Callable,
|
|
428
429
|
user_function: UserFunction,
|
|
429
430
|
/,
|
|
430
431
|
) -> None:
|
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.4.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,11 @@
|
|
|
1
|
+
oprattr/__init__.py,sha256=NPLnNea_NmyxQUX7DLqaC7YB67XATQ2gEhkPmBGpRpo,6044
|
|
2
|
+
oprattr/_operations.py,sha256=UruyOQGERwfiKgJTjJkt_C00BBVFvJMXes2tFxEkXJI,5985
|
|
3
|
+
oprattr/abstract.py,sha256=I3AYc8F79IMgH2esaKSvCTFelV_jFxWRuvXDuTZ8E94,1407
|
|
4
|
+
oprattr/mixins.py,sha256=_qqhReZu9Ta83irVihUrhggcObEj4lyp-3_S9K2hEog,16875
|
|
5
|
+
oprattr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
oprattr/typeface.py,sha256=FPGAdTZUmS_jd56PcZ5tCcUE_rXNubINBpVMQLRenvg,1214
|
|
7
|
+
oprattr/typeface.pyi,sha256=6gVdlDXtwl6Qyv07JWuRhM78VTGzds0pJ2KZUAAGcXs,113
|
|
8
|
+
oprattr-0.4.0.dist-info/METADATA,sha256=uCu_KrutswZW3e1YyOGuPa_ywL3dO818GJpBmRBFfwI,375
|
|
9
|
+
oprattr-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
+
oprattr-0.4.0.dist-info/licenses/LICENSE,sha256=m2oXG0JDq5RzaKTS57TvGyNq5cWcV4_nfmLZjzLdYTg,1513
|
|
11
|
+
oprattr-0.4.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/operators.py
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
A namespace for operators used by this package's `Object` class.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import builtins
|
|
6
|
-
import operator
|
|
7
|
-
import typing
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Operator:
|
|
11
|
-
"""Base class for enhanced operators."""
|
|
12
|
-
def __init__(self, __f: typing.Callable, operation: str):
|
|
13
|
-
self._f = __f
|
|
14
|
-
self._operation = operation
|
|
15
|
-
|
|
16
|
-
def __repr__(self):
|
|
17
|
-
"""Called for repr(self)."""
|
|
18
|
-
return self._operation
|
|
19
|
-
|
|
20
|
-
def __call__(self, *args, **kwds):
|
|
21
|
-
"""Called for self(*args, **kwds)."""
|
|
22
|
-
return self._f(*args, **kwds)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
eq = Operator(operator.eq, r'a == b')
|
|
26
|
-
ne = Operator(operator.ne, r'a != b')
|
|
27
|
-
lt = Operator(operator.lt, r'a < b')
|
|
28
|
-
le = Operator(operator.le, r'a <= b')
|
|
29
|
-
gt = Operator(operator.gt, r'a > b')
|
|
30
|
-
ge = Operator(operator.ge, r'a >= b')
|
|
31
|
-
abs = Operator(builtins.abs, r'abs(a)')
|
|
32
|
-
pos = Operator(operator.pos, r'+a')
|
|
33
|
-
neg = Operator(operator.neg, r'-a')
|
|
34
|
-
add = Operator(operator.add, r'a + b')
|
|
35
|
-
sub = Operator(operator.sub, r'a - b')
|
|
36
|
-
mul = Operator(operator.mul, r'a * b')
|
|
37
|
-
truediv = Operator(operator.truediv, r'a / b')
|
|
38
|
-
floordiv = Operator(operator.floordiv, r'a // b')
|
|
39
|
-
mod = Operator(operator.mod, r'a % b')
|
|
40
|
-
pow = Operator(builtins.pow, r'a ** b')
|
|
41
|
-
|
oprattr-0.2.0.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
oprattr/__init__.py,sha256=RSJjoTQWRT-C_OYYKHKlzHVQgvnA7yM1aDTs1k4XtjM,5557
|
|
2
|
-
oprattr/_operations.py,sha256=DiWIXLaTFQfI_IKHB89DqEgDLgxzeWpyY1CrbxLtQqI,5831
|
|
3
|
-
oprattr/abstract.py,sha256=TzTt9GkQ5KZc5kqajdLnn8EcvxzMj3SALSI5iJrB6Vk,3182
|
|
4
|
-
oprattr/mixins.py,sha256=KLgCsqIbE3WglZ3psrdRGb-agmVwBEqrASIpkGkDL54,16807
|
|
5
|
-
oprattr/operators.py,sha256=skqQpIezGSDbsmB2h-UNnxG_7aDGT6PsnvUkondpwOg,1154
|
|
6
|
-
oprattr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
oprattr-0.2.0.dist-info/METADATA,sha256=PwniUyhE28lVnnRoAcZCNAEgVF50AdxbqqND9Jdil_s,328
|
|
8
|
-
oprattr-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
-
oprattr-0.2.0.dist-info/RECORD,,
|
|
File without changes
|