xobjects 0.3.1__tar.gz → 0.4.0__tar.gz
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.
- {xobjects-0.3.1/xobjects.egg-info → xobjects-0.4.0}/PKG-INFO +1 -1
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_array.py +6 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_hybrid_class.py +20 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/__init__.py +2 -0
- xobjects-0.4.0/xobjects/_version.py +1 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/array.py +8 -4
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/context_cpu.py +6 -4
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/hybrid_class.py +52 -24
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/test_helpers.py +8 -0
- {xobjects-0.3.1 → xobjects-0.4.0/xobjects.egg-info}/PKG-INFO +1 -1
- xobjects-0.3.1/xobjects/_version.py +0 -1
- {xobjects-0.3.1 → xobjects-0.4.0}/LICENSE +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/pyproject.toml +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/setup.cfg +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/setup.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_align.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_buffer.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_capi.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_chunk.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_context_opencl.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_kernel.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_linked_array.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_nplike_arrays.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_ref.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_scalars.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_shared_memory.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_strides.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_string.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_struct.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_to_json.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_typeutils.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/tests/test_unionref.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/_patch_pyopencl_array.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/capi.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/context.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/context_cupy.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/context_pyopencl.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/general.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/linkedarray.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/ref.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/scalar.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/specialize_source.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/string.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/struct.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/typeutils.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects/union.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects.egg-info/SOURCES.txt +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects.egg-info/dependency_links.txt +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects.egg-info/requires.txt +0 -0
- {xobjects-0.3.1 → xobjects-0.4.0}/xobjects.egg-info/top_level.txt +0 -0
|
@@ -125,6 +125,12 @@ def test_array_allocation():
|
|
|
125
125
|
assert ss._itemtype == xo.Int64
|
|
126
126
|
|
|
127
127
|
|
|
128
|
+
def test_static_array_allocation_with_none():
|
|
129
|
+
MyArray = xo.Int64[10]
|
|
130
|
+
ss = MyArray(None)
|
|
131
|
+
assert ss._itemtype == xo.Int64
|
|
132
|
+
|
|
133
|
+
|
|
128
134
|
def test_array_sshape_stype():
|
|
129
135
|
Array1D = xo.Int64[3]
|
|
130
136
|
Array2D = xo.Int64[2, 3]
|
|
@@ -310,3 +310,23 @@ def test_move_field_of_nested_fails(classes_for_test_hybrid_class_ref):
|
|
|
310
310
|
|
|
311
311
|
with pytest.raises(MemoryError):
|
|
312
312
|
outer.inner.move(_buffer=different_buffer)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def test_to_json_defaults():
|
|
316
|
+
class A(xo.HybridClass):
|
|
317
|
+
_xofields = {
|
|
318
|
+
"a": xo.Float64[3],
|
|
319
|
+
"b": xo.Int64,
|
|
320
|
+
"c": xo.Field(xo.Int32, default=42),
|
|
321
|
+
"d": xo.Field(xo.Int32, default_factory=lambda: 7),
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
a = A(c=42)
|
|
325
|
+
assert a.to_dict() == {"__class__": "A"}
|
|
326
|
+
|
|
327
|
+
b = A(a=[1, 2, 3], d=8)
|
|
328
|
+
b_dict = b.to_dict()
|
|
329
|
+
assert b_dict.pop("__class__") == "A"
|
|
330
|
+
assert np.all(b_dict.pop("a") == [1, 2, 3])
|
|
331
|
+
assert b_dict.pop("d") == 8
|
|
332
|
+
assert b_dict == {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.0"
|
|
@@ -307,10 +307,14 @@ class Array(metaclass=MetaArray):
|
|
|
307
307
|
if len(args) == 0:
|
|
308
308
|
value = None
|
|
309
309
|
elif len(args) == 1:
|
|
310
|
-
|
|
311
|
-
if
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
(arg,) = args
|
|
311
|
+
if arg is None:
|
|
312
|
+
value = None
|
|
313
|
+
else:
|
|
314
|
+
shape = get_shape_from_array(arg, len(cls._shape))
|
|
315
|
+
if shape != cls._shape:
|
|
316
|
+
raise ValueError(f"shape not valid for {arg} ")
|
|
317
|
+
value = arg
|
|
314
318
|
elif len(args) > 1:
|
|
315
319
|
raise ValueError("too many arguments")
|
|
316
320
|
size = cls._size
|
|
@@ -146,7 +146,7 @@ class ContextCpu(XContext):
|
|
|
146
146
|
"""
|
|
147
147
|
super().__init__()
|
|
148
148
|
self.omp_num_threads = omp_num_threads
|
|
149
|
-
if omp_num_threads==0:
|
|
149
|
+
if omp_num_threads == 0:
|
|
150
150
|
self.allow_prebuilt_kernels = True
|
|
151
151
|
|
|
152
152
|
def __str__(self):
|
|
@@ -517,10 +517,12 @@ class ContextCpu(XContext):
|
|
|
517
517
|
def cffi_module_for_c_types(c_types, containing_dir="."):
|
|
518
518
|
path = Path(containing_dir)
|
|
519
519
|
for file in path.iterdir():
|
|
520
|
-
if not file.suffix in [
|
|
520
|
+
if not file.suffix in [".so", ".dylib", ".dll"]:
|
|
521
521
|
continue
|
|
522
|
-
module_name = file.name.split(
|
|
523
|
-
spec = importlib.util.spec_from_file_location(
|
|
522
|
+
module_name = file.name.split(".")[0]
|
|
523
|
+
spec = importlib.util.spec_from_file_location(
|
|
524
|
+
module_name, str(file)
|
|
525
|
+
)
|
|
524
526
|
module = importlib.util.module_from_spec(spec)
|
|
525
527
|
|
|
526
528
|
typedefs = module.ffi.list_types()[0]
|
|
@@ -40,13 +40,14 @@ class _FieldOfDressed:
|
|
|
40
40
|
if self.isnplikearray:
|
|
41
41
|
self.__get__(container=container)[:] = value
|
|
42
42
|
elif hasattr(value, "_xobject"): # value is a dressed xobject
|
|
43
|
+
|
|
43
44
|
# Copy xobject data from value inside self._xobject
|
|
44
45
|
# (unless same memory area or Ref and same buffer,
|
|
45
46
|
# in the latter case reference mechanism is used)
|
|
46
47
|
if not (
|
|
47
48
|
container._xobject._buffer is value._xobject._buffer
|
|
48
|
-
and getattr(container._xobject, self.name)
|
|
49
|
-
|
|
49
|
+
and (getattr(container._xobject, self.name) is not None and
|
|
50
|
+
getattr(container._xobject, self.name)._offset == value._xobject._offset)
|
|
50
51
|
):
|
|
51
52
|
setattr(container._xobject, self.name, value._xobject)
|
|
52
53
|
|
|
@@ -198,15 +199,16 @@ class MetaHybridClass(type):
|
|
|
198
199
|
class HybridClass(metaclass=MetaHybridClass):
|
|
199
200
|
_movable = True
|
|
200
201
|
_overridable = True
|
|
202
|
+
_force_moveable = False
|
|
201
203
|
|
|
202
204
|
def move(self, _context=None, _buffer=None, _offset=None):
|
|
203
|
-
if not self._movable:
|
|
205
|
+
if not self._movable and not self._force_moveable:
|
|
204
206
|
raise MemoryError(
|
|
205
207
|
"This object cannot be moved, likely because it "
|
|
206
208
|
"lives within another. Please, make a copy."
|
|
207
209
|
)
|
|
208
210
|
|
|
209
|
-
if self._xobject._has_refs:
|
|
211
|
+
if self._xobject._has_refs and not self._force_moveable:
|
|
210
212
|
raise MemoryError(
|
|
211
213
|
"This object cannot be moved, as it contains "
|
|
212
214
|
"references to other objects."
|
|
@@ -285,34 +287,33 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
285
287
|
else:
|
|
286
288
|
obj = self
|
|
287
289
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
290
|
+
skip_fields = set(getattr(obj, "_skip_in_to_dict", []))
|
|
291
|
+
additional_fields = set(getattr(obj, "_store_in_to_dict", []))
|
|
292
|
+
fields_to_store = (set(obj._fields) - skip_fields) | additional_fields
|
|
293
|
+
|
|
294
|
+
defaults = {}
|
|
295
|
+
for field in obj._XoStruct._fields:
|
|
296
|
+
try:
|
|
297
|
+
defaults[field.name] = field.get_default()
|
|
298
|
+
except (TypeError, ValueError):
|
|
299
|
+
# The above can fail with different error types
|
|
300
|
+
# if a field type is dynamic.
|
|
301
|
+
pass
|
|
302
|
+
|
|
303
|
+
for ff in fields_to_store:
|
|
294
304
|
vv = getattr(obj, ff)
|
|
295
305
|
if hasattr(vv, "to_dict"):
|
|
296
306
|
out[ff] = vv.to_dict()
|
|
297
307
|
elif hasattr(vv, "_to_dict"):
|
|
298
308
|
out[ff] = vv._to_dict()
|
|
299
|
-
|
|
309
|
+
elif np.any(defaults.get(ff) != vv):
|
|
310
|
+
# Only include those scalar values that are not default.
|
|
300
311
|
out[ff] = vv
|
|
301
312
|
|
|
302
|
-
if hasattr(obj, "_store_in_to_dict"):
|
|
303
|
-
for nn in obj._store_in_to_dict:
|
|
304
|
-
ww = getattr(obj, nn)
|
|
305
|
-
if hasattr(ww, "to_dict"):
|
|
306
|
-
out[nn] = ww.to_dict()
|
|
307
|
-
elif hasattr(ww, "_to_dict"):
|
|
308
|
-
out[nn] = ww._to_dict()
|
|
309
|
-
else:
|
|
310
|
-
out[nn] = ww
|
|
311
|
-
|
|
312
313
|
return out
|
|
313
314
|
|
|
314
|
-
@
|
|
315
|
-
def
|
|
315
|
+
@staticmethod
|
|
316
|
+
def _static_from_dict(cls, dct, _context=None, _buffer=None, _offset=None):
|
|
316
317
|
return cls(
|
|
317
318
|
**dct,
|
|
318
319
|
_context=_context,
|
|
@@ -321,6 +322,15 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
321
322
|
_kwargs_name_check=False,
|
|
322
323
|
)
|
|
323
324
|
|
|
325
|
+
@classmethod
|
|
326
|
+
def from_dict(cls, dct, _context=None, _buffer=None, _offset=None):
|
|
327
|
+
return HybridClass._static_from_dict(cls,
|
|
328
|
+
dct,
|
|
329
|
+
_context=_context,
|
|
330
|
+
_buffer=_buffer,
|
|
331
|
+
_offset=_offset,
|
|
332
|
+
)
|
|
333
|
+
|
|
324
334
|
def copy(self, _context=None, _buffer=None, _offset=None):
|
|
325
335
|
if _context is None and _buffer is None:
|
|
326
336
|
_context = self._xobject._buffer.context
|
|
@@ -367,7 +377,25 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
367
377
|
return self._xobject.compile_kernels(*args, **kwargs)
|
|
368
378
|
|
|
369
379
|
def __repr__(self):
|
|
370
|
-
|
|
380
|
+
|
|
381
|
+
if hasattr(self, "_repr_fields"):
|
|
382
|
+
fnames = self._repr_fields
|
|
383
|
+
else:
|
|
384
|
+
fnames = []
|
|
385
|
+
if hasattr(self, "_add_to_repr"):
|
|
386
|
+
fnames += self._add_to_repr
|
|
387
|
+
fnames += [fname for fname in self._fields]
|
|
388
|
+
if hasattr(self, "_skip_in_repr"):
|
|
389
|
+
fnames = [ff for ff in fnames if ff not in self._skip_in_repr]
|
|
390
|
+
|
|
391
|
+
args = []
|
|
392
|
+
for fname in fnames:
|
|
393
|
+
vv = getattr(self, fname)
|
|
394
|
+
if isinstance(vv, float):
|
|
395
|
+
vvrepr = f"{vv:.3g}"
|
|
396
|
+
else:
|
|
397
|
+
vvrepr = repr(vv)
|
|
398
|
+
args.append(f"{fname}={vvrepr}")
|
|
371
399
|
return f'{type(self).__name__}({", ".join(args)})'
|
|
372
400
|
|
|
373
401
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from functools import wraps
|
|
7
7
|
from typing import Callable, Iterable, Union
|
|
8
|
+
from numpy.testing import assert_allclose as np_assert_allclose
|
|
8
9
|
|
|
9
10
|
import pytest
|
|
10
11
|
|
|
@@ -83,3 +84,10 @@ def requires_context(context_name: str):
|
|
|
83
84
|
return lambda test_function: test_function
|
|
84
85
|
|
|
85
86
|
return pytest.mark.skip(f"{context_name} is unavailable on this platform.")
|
|
87
|
+
|
|
88
|
+
def assert_allclose(a, b, rtol=1e-7, atol=1e-7):
|
|
89
|
+
if hasattr(a, 'get'):
|
|
90
|
+
a = a.get()
|
|
91
|
+
if hasattr(b, 'get'):
|
|
92
|
+
b = b.get()
|
|
93
|
+
np_assert_allclose(a, b, rtol=rtol, atol=atol)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|