tinycwrap 0.0.3__tar.gz → 0.0.5__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.
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/PKG-INFO +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/pyproject.toml +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tests/test_geom.py +6 -0
- tinycwrap-0.0.3/tests/test_examples.py → tinycwrap-0.0.5/tests/test_kernels.py +3 -3
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tests/test_path.py +17 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap/__init__.py +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap/cmodule.py +81 -49
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap.egg-info/PKG-INFO +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap.egg-info/SOURCES.txt +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/README.md +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/setup.cfg +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap/parsing.py +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap.egg-info/dependency_links.txt +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap.egg-info/requires.txt +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.5}/tinycwrap.egg-info/top_level.txt +0 -0
|
@@ -27,12 +27,18 @@ def test_circle_points_length_contract(cg):
|
|
|
27
27
|
assert pts.shape == (101,)
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
|
|
30
31
|
def test_return_struct_array_member(cg):
|
|
31
32
|
seg = cg.G2DSegment()
|
|
32
33
|
seg.type = 1
|
|
33
34
|
seg.data = [0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0]
|
|
34
35
|
assert seg.type == 1
|
|
35
36
|
np.testing.assert_allclose(seg.data, [0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0])
|
|
37
|
+
seg= cg.G2DSegment(type=2, data=[9.0]*8)
|
|
38
|
+
assert seg.type == 2
|
|
39
|
+
np.testing.assert_allclose(seg.data, [9.0]*8)
|
|
40
|
+
|
|
41
|
+
|
|
36
42
|
|
|
37
43
|
def test_geom2d_return_strct(cg):
|
|
38
44
|
seg = cg.geom2d_line_segment_from_start_length(0.1, 0.2, 0.5, 0.4, 0.3)
|
|
@@ -14,9 +14,9 @@ def cm():
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def test_dot(cm):
|
|
17
|
-
x = np.
|
|
18
|
-
y = np.
|
|
19
|
-
assert cm.dot(x, y, len_x=len(x)) == np.
|
|
17
|
+
x = np.array([1.0, 2.0, 3.0], dtype=np.float64)
|
|
18
|
+
y = np.array([4.0, 5.0, 6.0], dtype=np.float64)
|
|
19
|
+
assert cm.dot(x, y, len_x=len(x)) == np.dot(x, y)
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def test_scale_auto_output(cm):
|
|
@@ -39,3 +39,20 @@ def test_return_class_path(cp):
|
|
|
39
39
|
seg = path.segments[0]
|
|
40
40
|
assert seg['type'] == 1 # circle segment
|
|
41
41
|
np.testing.assert_allclose(seg['data'][:3], [0.0, 0.0, 1.0]) # cx,cy,radius
|
|
42
|
+
|
|
43
|
+
def test_build_pointer_from_data(cp):
|
|
44
|
+
segments=cp.geom2d_rectangle_to_path(2.0, 3.0)
|
|
45
|
+
assert segments.shape == (4,)
|
|
46
|
+
path=cp.G2DPath(segments=segments, len_segments=len(segments))
|
|
47
|
+
assert path.len_segments == 4
|
|
48
|
+
assert path.segments.shape == (4,)
|
|
49
|
+
|
|
50
|
+
def test_repr_pointer_array(cp):
|
|
51
|
+
path = cp.G2DPath(len_segments=2)
|
|
52
|
+
repr_str = repr(path)
|
|
53
|
+
assert "segments=<segments* 0x" in repr_str
|
|
54
|
+
assert "len_segments=2" in repr_str
|
|
55
|
+
|
|
56
|
+
def test_post_contract(cp):
|
|
57
|
+
segments, len_segments = cp.geom2d_segments_from_rectellipse(1,2,3,4)
|
|
58
|
+
assert segments.shape == (4,)
|
|
@@ -381,24 +381,22 @@ class CModule:
|
|
|
381
381
|
fspec.doc = doc
|
|
382
382
|
contracts = []
|
|
383
383
|
for line in doc.splitlines():
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
mlen = re.match(r"
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
expr = mlen.group(2).strip()
|
|
401
|
-
contracts.append((target, expr, is_post))
|
|
384
|
+
m_contract = re.search(r"(post-)?contract:\s*(.*)", line, flags=re.IGNORECASE)
|
|
385
|
+
if not m_contract:
|
|
386
|
+
continue
|
|
387
|
+
is_post = m_contract.group(1) is not None
|
|
388
|
+
after = m_contract.group(2)
|
|
389
|
+
for part in after.split(";"):
|
|
390
|
+
part = part.strip()
|
|
391
|
+
if not part:
|
|
392
|
+
continue
|
|
393
|
+
mlen = re.match(r"len\((\w+)\)\s*=\s*(.+)", part)
|
|
394
|
+
if not mlen:
|
|
395
|
+
mlen = re.match(r"(\w+)\s*=\s*(.+)", part)
|
|
396
|
+
if mlen:
|
|
397
|
+
target = mlen.group(1)
|
|
398
|
+
expr = mlen.group(2).strip()
|
|
399
|
+
contracts.append((target, expr, is_post))
|
|
402
400
|
fspec.contracts = contracts or None
|
|
403
401
|
|
|
404
402
|
def _mark_length_params_from_contracts(self):
|
|
@@ -496,7 +494,15 @@ class CModule:
|
|
|
496
494
|
target_dtype = _struct_dtypes.get(f.base_type)
|
|
497
495
|
provided = kwargs.get(f.name)
|
|
498
496
|
if provided is not None and target_dtype is not None:
|
|
499
|
-
|
|
497
|
+
try:
|
|
498
|
+
arr = np.ascontiguousarray(provided, dtype=target_dtype)
|
|
499
|
+
except ValueError:
|
|
500
|
+
if hasattr(provided, "_data"):
|
|
501
|
+
arr = np.ascontiguousarray(provided._data, dtype=target_dtype)
|
|
502
|
+
elif isinstance(provided, (list, tuple)) and provided and hasattr(provided[0], "_data"):
|
|
503
|
+
arr = np.ascontiguousarray([p._data for p in provided], dtype=target_dtype)
|
|
504
|
+
else:
|
|
505
|
+
raise
|
|
500
506
|
children[f.name] = arr
|
|
501
507
|
data[f.name] = arr.ctypes.data
|
|
502
508
|
if len_field in dtype.names and len_field not in kwargs:
|
|
@@ -507,15 +513,51 @@ class CModule:
|
|
|
507
513
|
children[f.name] = arr
|
|
508
514
|
data[f.name] = arr.ctypes.data
|
|
509
515
|
data[len_field] = llen
|
|
516
|
+
elif provided is not None:
|
|
517
|
+
arr = np.ascontiguousarray(provided)
|
|
518
|
+
children[f.name] = arr
|
|
519
|
+
data[f.name] = arr.ctypes.data
|
|
520
|
+
if len_field in dtype.names and len_field not in kwargs:
|
|
521
|
+
data[len_field] = len(arr)
|
|
522
|
+
elif target_dtype is not None and len_field in dtype.names:
|
|
523
|
+
llen = int(kwargs.get(len_field, 1))
|
|
524
|
+
arr = np.zeros(llen, dtype=target_dtype)
|
|
525
|
+
children[f.name] = arr
|
|
526
|
+
data[f.name] = arr.ctypes.data
|
|
527
|
+
data[len_field] = llen
|
|
510
528
|
for k in dtype.names:
|
|
511
529
|
if k in kwargs:
|
|
512
|
-
|
|
530
|
+
val = kwargs[k]
|
|
531
|
+
field_info = dtype.fields[k][0]
|
|
532
|
+
if field_info.shape != ():
|
|
533
|
+
arr = np.asarray(val, dtype=field_info.base)
|
|
534
|
+
if arr.shape != field_info.shape:
|
|
535
|
+
raise ValueError(f"Field {k} expects shape {field_info.shape}, got {arr.shape}")
|
|
536
|
+
np.copyto(data[k], arr)
|
|
537
|
+
else:
|
|
538
|
+
if k in children:
|
|
539
|
+
data[k] = children[k].ctypes.data
|
|
540
|
+
elif isinstance(val, np.ndarray):
|
|
541
|
+
if val.dtype.kind == "V" and val.shape != ():
|
|
542
|
+
arr = np.ascontiguousarray(val)
|
|
543
|
+
data[k] = arr.ctypes.data
|
|
544
|
+
if f"len_{k}" in dtype.names and f"len_{k}" not in kwargs:
|
|
545
|
+
data[f"len_{k}"] = len(arr)
|
|
546
|
+
else:
|
|
547
|
+
data[k] = val
|
|
548
|
+
else:
|
|
549
|
+
data[k] = val
|
|
513
550
|
object.__setattr__(self, "_data", data)
|
|
514
551
|
object.__setattr__(self, "_children", children)
|
|
515
552
|
|
|
516
553
|
def __repr__(self):
|
|
517
554
|
parts_list = []
|
|
555
|
+
pointer_lengths = getattr(self, "_pointer_lengths", {})
|
|
518
556
|
for name in dtype.names:
|
|
557
|
+
if name in pointer_lengths:
|
|
558
|
+
ptr_val = int(self._data[name])
|
|
559
|
+
parts_list.append(f"{name}=<{name}* 0x{ptr_val:x}>")
|
|
560
|
+
continue
|
|
519
561
|
val = self._data[name]
|
|
520
562
|
if val.shape == ():
|
|
521
563
|
parts_list.append(f"{name}={val.item()!r}")
|
|
@@ -533,6 +575,7 @@ class CModule:
|
|
|
533
575
|
"zeros": staticmethod(
|
|
534
576
|
lambda n, _dtype=dtype: np.zeros(n, dtype=_dtype)
|
|
535
577
|
),
|
|
578
|
+
"_pointer_lengths": {f.name: f"len_{f.name}" for f in spec.fields if f.is_pointer},
|
|
536
579
|
}
|
|
537
580
|
|
|
538
581
|
for fname in dtype.names:
|
|
@@ -632,20 +675,26 @@ class CModule:
|
|
|
632
675
|
struct_names = set(self._struct_specs.keys())
|
|
633
676
|
params: list[str] = []
|
|
634
677
|
len_params: list[str] = []
|
|
678
|
+
optional_seen = False
|
|
635
679
|
for a in fspec.args:
|
|
636
680
|
if a.is_array_out and a.name.lower().startswith("out"):
|
|
637
681
|
params.append(f"{a.name}=None")
|
|
682
|
+
optional_seen = True
|
|
638
683
|
elif a.is_length_param:
|
|
639
684
|
len_params.append(f"{a.name}=None")
|
|
685
|
+
optional_seen = True
|
|
640
686
|
elif (
|
|
641
687
|
a.is_pointer
|
|
642
688
|
and a.base_type in struct_names
|
|
643
689
|
and not a.is_const
|
|
644
|
-
and a.name.lower().startswith("out")
|
|
645
690
|
):
|
|
646
691
|
params.append(f"{a.name}=None")
|
|
692
|
+
optional_seen = True
|
|
647
693
|
else:
|
|
648
|
-
|
|
694
|
+
if optional_seen:
|
|
695
|
+
params.append(f"{a.name}=None")
|
|
696
|
+
else:
|
|
697
|
+
params.append(a.name)
|
|
649
698
|
|
|
650
699
|
params.extend(len_params)
|
|
651
700
|
signature = ", ".join(params)
|
|
@@ -763,11 +812,10 @@ class CModule:
|
|
|
763
812
|
if a.is_array_in:
|
|
764
813
|
const_prefix = "const " if a.is_const else ""
|
|
765
814
|
if a.base_type in struct_names:
|
|
766
|
-
cls_expr = f"_struct_classes['{a.base_type}']"
|
|
767
815
|
dtype_expr = f"_struct_dtypes['{a.base_type}']"
|
|
768
816
|
pre_lines += [
|
|
769
|
-
f" if
|
|
770
|
-
f" arr_{a.name} = {a.name}
|
|
817
|
+
f" if hasattr({a.name}, '_data') and getattr({a.name}, '_data', None) is not None and getattr({a.name}, '_data').dtype == {dtype_expr}:",
|
|
818
|
+
f" arr_{a.name} = getattr({a.name}, '_data')",
|
|
771
819
|
" else:",
|
|
772
820
|
f" arr_{a.name} = np.ascontiguousarray({a.name}, dtype={dtype_expr})",
|
|
773
821
|
f" ptr_{a.name} = _self._ffi.cast('{const_prefix}{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
@@ -872,11 +920,10 @@ class CModule:
|
|
|
872
920
|
)
|
|
873
921
|
elif a.is_pointer and a.base_type in struct_names:
|
|
874
922
|
dtype_expr = f"_struct_dtypes['{a.base_type}']"
|
|
875
|
-
cls_expr = f"_struct_classes['{a.base_type}']"
|
|
876
923
|
if a.is_const:
|
|
877
924
|
out_lines += [
|
|
878
|
-
f" if
|
|
879
|
-
f" arr_{a.name} = {a.name}
|
|
925
|
+
f" if hasattr({a.name}, '_data') and getattr({a.name}, '_data', None) is not None and getattr({a.name}, '_data').dtype == {dtype_expr}:",
|
|
926
|
+
f" arr_{a.name} = getattr({a.name}, '_data')",
|
|
880
927
|
" else:",
|
|
881
928
|
f" arr_{a.name} = np.ascontiguousarray({a.name}, dtype={dtype_expr})",
|
|
882
929
|
f" ptr_{a.name} = _self._ffi.cast('{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
@@ -884,33 +931,18 @@ class CModule:
|
|
|
884
931
|
else:
|
|
885
932
|
out_lines += [
|
|
886
933
|
f" if {a.name} is None:",
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
]
|
|
892
|
-
elif a.name in contract_map:
|
|
893
|
-
expr_py = _expr_py(contract_map[a.name])
|
|
894
|
-
out_lines += [
|
|
895
|
-
f" arr_{a.name} = np.zeros(int({expr_py}), dtype={dtype_expr})"
|
|
896
|
-
]
|
|
897
|
-
elif a.array_len is None and a.name not in contract_map:
|
|
898
|
-
out_lines += [
|
|
899
|
-
f" arr_{a.name} = np.zeros((), dtype={dtype_expr})"
|
|
900
|
-
]
|
|
901
|
-
else:
|
|
902
|
-
out_lines += [
|
|
903
|
-
f" raise ValueError('{fspec.name}: provide {a.name} or a Contract for its length')"
|
|
904
|
-
]
|
|
905
|
-
out_lines += [
|
|
906
|
-
f" elif isinstance({a.name}, {cls_expr}):",
|
|
934
|
+
f" obj_{a.name} = _struct_classes['{a.base_type}']()",
|
|
935
|
+
f" arr_{a.name} = obj_{a.name}._data",
|
|
936
|
+
f" elif hasattr({a.name}, '_data') and getattr({a.name}, '_data', None) is not None and getattr({a.name}, '_data').dtype == {dtype_expr}:",
|
|
937
|
+
f" obj_{a.name} = {a.name}",
|
|
907
938
|
f" arr_{a.name} = {a.name}._data",
|
|
908
939
|
" else:",
|
|
909
940
|
f" arr_{a.name} = np.ascontiguousarray({a.name}, dtype={dtype_expr})",
|
|
941
|
+
f" obj_{a.name} = None",
|
|
910
942
|
f" ptr_{a.name} = _self._ffi.cast('{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
911
943
|
]
|
|
912
944
|
output_names.append(a.name)
|
|
913
|
-
output_vars.append(f"arr_{a.name}")
|
|
945
|
+
output_vars.append(f"obj_{a.name} if obj_{a.name} is not None else arr_{a.name}")
|
|
914
946
|
arg_call_args[idx] = f"ptr_{a.name}"
|
|
915
947
|
elif a.is_scalar and not a.is_length_param and arg_call_args[idx] is None:
|
|
916
948
|
scalar_lines.append(f" {a.name} = {a.name}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|