xobjects 0.3.1__tar.gz → 0.4.1__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.1}/PKG-INFO +1 -1
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_array.py +6 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_hybrid_class.py +20 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/__init__.py +2 -0
- xobjects-0.4.1/xobjects/_version.py +1 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/array.py +8 -4
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/context_cpu.py +6 -4
- xobjects-0.4.1/xobjects/general.py +24 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/hybrid_class.py +56 -24
- {xobjects-0.3.1 → xobjects-0.4.1/xobjects.egg-info}/PKG-INFO +1 -1
- xobjects-0.3.1/xobjects/_version.py +0 -1
- xobjects-0.3.1/xobjects/general.py +0 -9
- {xobjects-0.3.1 → xobjects-0.4.1}/LICENSE +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/pyproject.toml +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/setup.cfg +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/setup.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_align.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_buffer.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_capi.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_chunk.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_context_opencl.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_kernel.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_linked_array.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_nplike_arrays.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_ref.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_scalars.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_shared_memory.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_strides.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_string.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_struct.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_to_json.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_typeutils.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/tests/test_unionref.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/_patch_pyopencl_array.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/capi.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/context.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/context_cupy.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/context_pyopencl.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/linkedarray.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/ref.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/scalar.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/specialize_source.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/string.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/struct.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/test_helpers.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/typeutils.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects/union.py +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects.egg-info/SOURCES.txt +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects.egg-info/dependency_links.txt +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/xobjects.egg-info/requires.txt +0 -0
- {xobjects-0.3.1 → xobjects-0.4.1}/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.1"
|
|
@@ -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]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# copyright ################################# #
|
|
2
|
+
# This file is part of the Xobjects Package. #
|
|
3
|
+
# Copyright (c) CERN, 2024. #
|
|
4
|
+
# ########################################### #
|
|
5
|
+
from numpy.testing import assert_allclose as np_assert_allclose
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Print:
|
|
9
|
+
suppress = False
|
|
10
|
+
|
|
11
|
+
def __call__(self, *args, **kwargs):
|
|
12
|
+
if not self.suppress:
|
|
13
|
+
print(*args, **kwargs)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_print = Print()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def assert_allclose(a, b, rtol=1e-7, atol=1e-7):
|
|
20
|
+
if hasattr(a, "get"):
|
|
21
|
+
a = a.get()
|
|
22
|
+
if hasattr(b, "get"):
|
|
23
|
+
b = b.get()
|
|
24
|
+
np_assert_allclose(a, b, rtol=rtol, atol=atol)
|
|
@@ -40,13 +40,17 @@ 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
|
|
49
|
-
|
|
49
|
+
and (
|
|
50
|
+
getattr(container._xobject, self.name) is not None
|
|
51
|
+
and getattr(container._xobject, self.name)._offset
|
|
52
|
+
== value._xobject._offset
|
|
53
|
+
)
|
|
50
54
|
):
|
|
51
55
|
setattr(container._xobject, self.name, value._xobject)
|
|
52
56
|
|
|
@@ -198,15 +202,16 @@ class MetaHybridClass(type):
|
|
|
198
202
|
class HybridClass(metaclass=MetaHybridClass):
|
|
199
203
|
_movable = True
|
|
200
204
|
_overridable = True
|
|
205
|
+
_force_moveable = False
|
|
201
206
|
|
|
202
207
|
def move(self, _context=None, _buffer=None, _offset=None):
|
|
203
|
-
if not self._movable:
|
|
208
|
+
if not self._movable and not self._force_moveable:
|
|
204
209
|
raise MemoryError(
|
|
205
210
|
"This object cannot be moved, likely because it "
|
|
206
211
|
"lives within another. Please, make a copy."
|
|
207
212
|
)
|
|
208
213
|
|
|
209
|
-
if self._xobject._has_refs:
|
|
214
|
+
if self._xobject._has_refs and not self._force_moveable:
|
|
210
215
|
raise MemoryError(
|
|
211
216
|
"This object cannot be moved, as it contains "
|
|
212
217
|
"references to other objects."
|
|
@@ -285,34 +290,33 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
285
290
|
else:
|
|
286
291
|
obj = self
|
|
287
292
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
skip_fields = set(getattr(obj, "_skip_in_to_dict", []))
|
|
294
|
+
additional_fields = set(getattr(obj, "_store_in_to_dict", []))
|
|
295
|
+
fields_to_store = (set(obj._fields) - skip_fields) | additional_fields
|
|
296
|
+
|
|
297
|
+
defaults = {}
|
|
298
|
+
for field in obj._XoStruct._fields:
|
|
299
|
+
try:
|
|
300
|
+
defaults[field.name] = field.get_default()
|
|
301
|
+
except (TypeError, ValueError):
|
|
302
|
+
# The above can fail with different error types
|
|
303
|
+
# if a field type is dynamic.
|
|
304
|
+
pass
|
|
305
|
+
|
|
306
|
+
for ff in fields_to_store:
|
|
294
307
|
vv = getattr(obj, ff)
|
|
295
308
|
if hasattr(vv, "to_dict"):
|
|
296
309
|
out[ff] = vv.to_dict()
|
|
297
310
|
elif hasattr(vv, "_to_dict"):
|
|
298
311
|
out[ff] = vv._to_dict()
|
|
299
|
-
|
|
312
|
+
elif np.any(defaults.get(ff) != vv):
|
|
313
|
+
# Only include those scalar values that are not default.
|
|
300
314
|
out[ff] = vv
|
|
301
315
|
|
|
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
316
|
return out
|
|
313
317
|
|
|
314
|
-
@
|
|
315
|
-
def
|
|
318
|
+
@staticmethod
|
|
319
|
+
def _static_from_dict(cls, dct, _context=None, _buffer=None, _offset=None):
|
|
316
320
|
return cls(
|
|
317
321
|
**dct,
|
|
318
322
|
_context=_context,
|
|
@@ -321,6 +325,16 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
321
325
|
_kwargs_name_check=False,
|
|
322
326
|
)
|
|
323
327
|
|
|
328
|
+
@classmethod
|
|
329
|
+
def from_dict(cls, dct, _context=None, _buffer=None, _offset=None):
|
|
330
|
+
return HybridClass._static_from_dict(
|
|
331
|
+
cls,
|
|
332
|
+
dct,
|
|
333
|
+
_context=_context,
|
|
334
|
+
_buffer=_buffer,
|
|
335
|
+
_offset=_offset,
|
|
336
|
+
)
|
|
337
|
+
|
|
324
338
|
def copy(self, _context=None, _buffer=None, _offset=None):
|
|
325
339
|
if _context is None and _buffer is None:
|
|
326
340
|
_context = self._xobject._buffer.context
|
|
@@ -367,7 +381,25 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
367
381
|
return self._xobject.compile_kernels(*args, **kwargs)
|
|
368
382
|
|
|
369
383
|
def __repr__(self):
|
|
370
|
-
|
|
384
|
+
|
|
385
|
+
if hasattr(self, "_repr_fields"):
|
|
386
|
+
fnames = self._repr_fields
|
|
387
|
+
else:
|
|
388
|
+
fnames = []
|
|
389
|
+
if hasattr(self, "_add_to_repr"):
|
|
390
|
+
fnames += self._add_to_repr
|
|
391
|
+
fnames += [fname for fname in self._fields]
|
|
392
|
+
if hasattr(self, "_skip_in_repr"):
|
|
393
|
+
fnames = [ff for ff in fnames if ff not in self._skip_in_repr]
|
|
394
|
+
|
|
395
|
+
args = []
|
|
396
|
+
for fname in fnames:
|
|
397
|
+
vv = getattr(self, fname)
|
|
398
|
+
if isinstance(vv, float):
|
|
399
|
+
vvrepr = f"{vv:.3g}"
|
|
400
|
+
else:
|
|
401
|
+
vvrepr = repr(vv)
|
|
402
|
+
args.append(f"{fname}={vvrepr}")
|
|
371
403
|
return f'{type(self).__name__}({", ".join(args)})'
|
|
372
404
|
|
|
373
405
|
|
|
@@ -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
|