tinycwrap 0.0.3__tar.gz → 0.0.4__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.4}/PKG-INFO +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/pyproject.toml +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tests/test_geom.py +6 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tests/test_path.py +13 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap/__init__.py +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap/cmodule.py +56 -30
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap.egg-info/PKG-INFO +1 -1
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/README.md +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/setup.cfg +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tests/test_examples.py +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap/parsing.py +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap.egg-info/SOURCES.txt +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap.egg-info/dependency_links.txt +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/tinycwrap.egg-info/requires.txt +0 -0
- {tinycwrap-0.0.3 → tinycwrap-0.0.4}/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)
|
|
@@ -39,3 +39,16 @@ 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
|
|
@@ -507,15 +507,51 @@ class CModule:
|
|
|
507
507
|
children[f.name] = arr
|
|
508
508
|
data[f.name] = arr.ctypes.data
|
|
509
509
|
data[len_field] = llen
|
|
510
|
+
elif provided is not None:
|
|
511
|
+
arr = np.ascontiguousarray(provided)
|
|
512
|
+
children[f.name] = arr
|
|
513
|
+
data[f.name] = arr.ctypes.data
|
|
514
|
+
if len_field in dtype.names and len_field not in kwargs:
|
|
515
|
+
data[len_field] = len(arr)
|
|
516
|
+
elif target_dtype is not None and len_field in dtype.names:
|
|
517
|
+
llen = int(kwargs.get(len_field, 1))
|
|
518
|
+
arr = np.zeros(llen, dtype=target_dtype)
|
|
519
|
+
children[f.name] = arr
|
|
520
|
+
data[f.name] = arr.ctypes.data
|
|
521
|
+
data[len_field] = llen
|
|
510
522
|
for k in dtype.names:
|
|
511
523
|
if k in kwargs:
|
|
512
|
-
|
|
524
|
+
val = kwargs[k]
|
|
525
|
+
field_info = dtype.fields[k][0]
|
|
526
|
+
if field_info.shape != ():
|
|
527
|
+
arr = np.asarray(val, dtype=field_info.base)
|
|
528
|
+
if arr.shape != field_info.shape:
|
|
529
|
+
raise ValueError(f"Field {k} expects shape {field_info.shape}, got {arr.shape}")
|
|
530
|
+
np.copyto(data[k], arr)
|
|
531
|
+
else:
|
|
532
|
+
if k in children:
|
|
533
|
+
data[k] = children[k].ctypes.data
|
|
534
|
+
elif isinstance(val, np.ndarray):
|
|
535
|
+
if val.dtype.kind == "V" and val.shape != ():
|
|
536
|
+
arr = np.ascontiguousarray(val)
|
|
537
|
+
data[k] = arr.ctypes.data
|
|
538
|
+
if f"len_{k}" in dtype.names and f"len_{k}" not in kwargs:
|
|
539
|
+
data[f"len_{k}"] = len(arr)
|
|
540
|
+
else:
|
|
541
|
+
data[k] = val
|
|
542
|
+
else:
|
|
543
|
+
data[k] = val
|
|
513
544
|
object.__setattr__(self, "_data", data)
|
|
514
545
|
object.__setattr__(self, "_children", children)
|
|
515
546
|
|
|
516
547
|
def __repr__(self):
|
|
517
548
|
parts_list = []
|
|
549
|
+
pointer_lengths = getattr(self, "_pointer_lengths", {})
|
|
518
550
|
for name in dtype.names:
|
|
551
|
+
if name in pointer_lengths:
|
|
552
|
+
ptr_val = int(self._data[name])
|
|
553
|
+
parts_list.append(f"{name}=<{name}* 0x{ptr_val:x}>")
|
|
554
|
+
continue
|
|
519
555
|
val = self._data[name]
|
|
520
556
|
if val.shape == ():
|
|
521
557
|
parts_list.append(f"{name}={val.item()!r}")
|
|
@@ -533,6 +569,7 @@ class CModule:
|
|
|
533
569
|
"zeros": staticmethod(
|
|
534
570
|
lambda n, _dtype=dtype: np.zeros(n, dtype=_dtype)
|
|
535
571
|
),
|
|
572
|
+
"_pointer_lengths": {f.name: f"len_{f.name}" for f in spec.fields if f.is_pointer},
|
|
536
573
|
}
|
|
537
574
|
|
|
538
575
|
for fname in dtype.names:
|
|
@@ -632,20 +669,26 @@ class CModule:
|
|
|
632
669
|
struct_names = set(self._struct_specs.keys())
|
|
633
670
|
params: list[str] = []
|
|
634
671
|
len_params: list[str] = []
|
|
672
|
+
optional_seen = False
|
|
635
673
|
for a in fspec.args:
|
|
636
674
|
if a.is_array_out and a.name.lower().startswith("out"):
|
|
637
675
|
params.append(f"{a.name}=None")
|
|
676
|
+
optional_seen = True
|
|
638
677
|
elif a.is_length_param:
|
|
639
678
|
len_params.append(f"{a.name}=None")
|
|
679
|
+
optional_seen = True
|
|
640
680
|
elif (
|
|
641
681
|
a.is_pointer
|
|
642
682
|
and a.base_type in struct_names
|
|
643
683
|
and not a.is_const
|
|
644
|
-
and a.name.lower().startswith("out")
|
|
645
684
|
):
|
|
646
685
|
params.append(f"{a.name}=None")
|
|
686
|
+
optional_seen = True
|
|
647
687
|
else:
|
|
648
|
-
|
|
688
|
+
if optional_seen:
|
|
689
|
+
params.append(f"{a.name}=None")
|
|
690
|
+
else:
|
|
691
|
+
params.append(a.name)
|
|
649
692
|
|
|
650
693
|
params.extend(len_params)
|
|
651
694
|
signature = ", ".join(params)
|
|
@@ -763,11 +806,10 @@ class CModule:
|
|
|
763
806
|
if a.is_array_in:
|
|
764
807
|
const_prefix = "const " if a.is_const else ""
|
|
765
808
|
if a.base_type in struct_names:
|
|
766
|
-
cls_expr = f"_struct_classes['{a.base_type}']"
|
|
767
809
|
dtype_expr = f"_struct_dtypes['{a.base_type}']"
|
|
768
810
|
pre_lines += [
|
|
769
|
-
f" if
|
|
770
|
-
f" arr_{a.name} = {a.name}
|
|
811
|
+
f" if hasattr({a.name}, '_data') and getattr({a.name}, '_data', None) is not None and getattr({a.name}, '_data').dtype == {dtype_expr}:",
|
|
812
|
+
f" arr_{a.name} = getattr({a.name}, '_data')",
|
|
771
813
|
" else:",
|
|
772
814
|
f" arr_{a.name} = np.ascontiguousarray({a.name}, dtype={dtype_expr})",
|
|
773
815
|
f" ptr_{a.name} = _self._ffi.cast('{const_prefix}{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
@@ -872,11 +914,10 @@ class CModule:
|
|
|
872
914
|
)
|
|
873
915
|
elif a.is_pointer and a.base_type in struct_names:
|
|
874
916
|
dtype_expr = f"_struct_dtypes['{a.base_type}']"
|
|
875
|
-
cls_expr = f"_struct_classes['{a.base_type}']"
|
|
876
917
|
if a.is_const:
|
|
877
918
|
out_lines += [
|
|
878
|
-
f" if
|
|
879
|
-
f" arr_{a.name} = {a.name}
|
|
919
|
+
f" if hasattr({a.name}, '_data') and getattr({a.name}, '_data', None) is not None and getattr({a.name}, '_data').dtype == {dtype_expr}:",
|
|
920
|
+
f" arr_{a.name} = getattr({a.name}, '_data')",
|
|
880
921
|
" else:",
|
|
881
922
|
f" arr_{a.name} = np.ascontiguousarray({a.name}, dtype={dtype_expr})",
|
|
882
923
|
f" ptr_{a.name} = _self._ffi.cast('{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
@@ -884,33 +925,18 @@ class CModule:
|
|
|
884
925
|
else:
|
|
885
926
|
out_lines += [
|
|
886
927
|
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}):",
|
|
928
|
+
f" obj_{a.name} = _struct_classes['{a.base_type}']()",
|
|
929
|
+
f" arr_{a.name} = obj_{a.name}._data",
|
|
930
|
+
f" elif hasattr({a.name}, '_data') and getattr({a.name}, '_data', None) is not None and getattr({a.name}, '_data').dtype == {dtype_expr}:",
|
|
931
|
+
f" obj_{a.name} = {a.name}",
|
|
907
932
|
f" arr_{a.name} = {a.name}._data",
|
|
908
933
|
" else:",
|
|
909
934
|
f" arr_{a.name} = np.ascontiguousarray({a.name}, dtype={dtype_expr})",
|
|
935
|
+
f" obj_{a.name} = None",
|
|
910
936
|
f" ptr_{a.name} = _self._ffi.cast('{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
911
937
|
]
|
|
912
938
|
output_names.append(a.name)
|
|
913
|
-
output_vars.append(f"arr_{a.name}")
|
|
939
|
+
output_vars.append(f"obj_{a.name} if obj_{a.name} is not None else arr_{a.name}")
|
|
914
940
|
arg_call_args[idx] = f"ptr_{a.name}"
|
|
915
941
|
elif a.is_scalar and not a.is_length_param and arg_call_args[idx] is None:
|
|
916
942
|
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
|
|
File without changes
|
|
File without changes
|