tinycwrap 0.0.2__tar.gz → 0.0.3__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.2 → tinycwrap-0.0.3}/PKG-INFO +1 -1
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/pyproject.toml +1 -1
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tests/test_geom.py +9 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tests/test_path.py +18 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap/__init__.py +1 -1
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap/cmodule.py +42 -4
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap/parsing.py +1 -9
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap.egg-info/PKG-INFO +1 -1
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/README.md +0 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/setup.cfg +0 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tests/test_examples.py +0 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap.egg-info/SOURCES.txt +0 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap.egg-info/dependency_links.txt +0 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap.egg-info/requires.txt +0 -0
- {tinycwrap-0.0.2 → tinycwrap-0.0.3}/tinycwrap.egg-info/top_level.txt +0 -0
|
@@ -52,3 +52,12 @@ def test_docstring_contains_contract(cg):
|
|
|
52
52
|
doc = cg.geom2d_rectangle_to_path.__doc__
|
|
53
53
|
assert "Contract: len(out_segments)=4" in doc
|
|
54
54
|
assert "Auto-wrapped C function `geom2d_rectangle_to_path`." in doc
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_polygon_length(cg):
|
|
58
|
+
pts = cg.G2DPoints(len_points=3)
|
|
59
|
+
pts.points[0]["x"] = 0.0; pts.points[0]["y"] = 0.0
|
|
60
|
+
pts.points[1]["x"] = 1.0; pts.points[1]["y"] = 0.0
|
|
61
|
+
pts.points[2]["x"] = 1.0; pts.points[2]["y"] = 1.0
|
|
62
|
+
length = cg.geom2d_polygon_length(pts.points)
|
|
63
|
+
assert length == 2.0
|
|
@@ -21,3 +21,21 @@ def test_path_get_steps_contract(cp):
|
|
|
21
21
|
expected_len = cp.geom2d_path_get_len_steps(segments, len_segments=len(segments), ds_min=0.25)
|
|
22
22
|
assert len(steps) == expected_len
|
|
23
23
|
assert np.isclose(steps[-1], cp.geom2d_path_get_length(segments, len_segments=1))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_path_struct_pointer_array(cp):
|
|
27
|
+
path = cp.G2DPath(len_segments=3)
|
|
28
|
+
assert path.len_segments == 3
|
|
29
|
+
assert isinstance(path.segments, np.ndarray)
|
|
30
|
+
assert path.segments.shape == (3,)
|
|
31
|
+
assert path.segments.dtype == cp.G2DSegment.dtype
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_return_class_path(cp):
|
|
35
|
+
path=cp.G2DPath(len_segments=1)
|
|
36
|
+
cp.geom2d_path_from_circle(1.0, path)
|
|
37
|
+
assert path.len_segments == 1
|
|
38
|
+
assert path.segments.shape == (1,)
|
|
39
|
+
seg = path.segments[0]
|
|
40
|
+
assert seg['type'] == 1 # circle segment
|
|
41
|
+
np.testing.assert_allclose(seg['data'][:3], [0.0, 0.0, 1.0]) # cx,cy,radius
|
|
@@ -462,8 +462,19 @@ class CModule:
|
|
|
462
462
|
for sname, sspec in self._struct_specs.items():
|
|
463
463
|
try:
|
|
464
464
|
dtype_fields = []
|
|
465
|
+
pointer_meta = []
|
|
465
466
|
for f in sspec.fields:
|
|
466
|
-
|
|
467
|
+
try:
|
|
468
|
+
base_dtype = numpy_dtype_for_base_type(f.base_type)
|
|
469
|
+
except TypeError:
|
|
470
|
+
base_dtype = None
|
|
471
|
+
if f.is_pointer:
|
|
472
|
+
dtype_fields.append((f.name, np.uintp))
|
|
473
|
+
pointer_meta.append(f)
|
|
474
|
+
if base_dtype is None:
|
|
475
|
+
continue
|
|
476
|
+
if base_dtype is None:
|
|
477
|
+
continue
|
|
467
478
|
if f.array_len:
|
|
468
479
|
dtype_fields.append((f.name, (base_dtype, (f.array_len,))))
|
|
469
480
|
else:
|
|
@@ -472,15 +483,35 @@ class CModule:
|
|
|
472
483
|
except TypeError:
|
|
473
484
|
continue
|
|
474
485
|
|
|
475
|
-
def make_struct_class(spec, dtype):
|
|
476
|
-
slots = ("_data",)
|
|
486
|
+
def make_struct_class(spec, dtype, _struct_dtypes=self._struct_dtypes):
|
|
487
|
+
slots = ("_data", "_children")
|
|
477
488
|
|
|
478
489
|
def __init__(self, **kwargs):
|
|
479
490
|
data = np.zeros((), dtype=dtype)
|
|
491
|
+
children = {}
|
|
492
|
+
# handle pointer+len convention
|
|
493
|
+
for f in spec.fields:
|
|
494
|
+
if f.is_pointer and f.name in dtype.names:
|
|
495
|
+
len_field = f"len_{f.name}"
|
|
496
|
+
target_dtype = _struct_dtypes.get(f.base_type)
|
|
497
|
+
provided = kwargs.get(f.name)
|
|
498
|
+
if provided is not None and target_dtype is not None:
|
|
499
|
+
arr = np.ascontiguousarray(provided, dtype=target_dtype)
|
|
500
|
+
children[f.name] = arr
|
|
501
|
+
data[f.name] = arr.ctypes.data
|
|
502
|
+
if len_field in dtype.names and len_field not in kwargs:
|
|
503
|
+
data[len_field] = len(arr)
|
|
504
|
+
elif len_field in kwargs and target_dtype is not None:
|
|
505
|
+
llen = int(kwargs[len_field])
|
|
506
|
+
arr = np.zeros(llen, dtype=target_dtype)
|
|
507
|
+
children[f.name] = arr
|
|
508
|
+
data[f.name] = arr.ctypes.data
|
|
509
|
+
data[len_field] = llen
|
|
480
510
|
for k in dtype.names:
|
|
481
511
|
if k in kwargs:
|
|
482
512
|
data[k] = kwargs[k]
|
|
483
513
|
object.__setattr__(self, "_data", data)
|
|
514
|
+
object.__setattr__(self, "_children", children)
|
|
484
515
|
|
|
485
516
|
def __repr__(self):
|
|
486
517
|
parts_list = []
|
|
@@ -508,7 +539,9 @@ class CModule:
|
|
|
508
539
|
field_info = dtype.fields[fname][0]
|
|
509
540
|
is_scalar = field_info.shape == ()
|
|
510
541
|
|
|
511
|
-
def getter(self, fname=fname, is_scalar=is_scalar):
|
|
542
|
+
def getter(self, fname=fname, is_scalar=is_scalar, field_info=field_info):
|
|
543
|
+
if fname in getattr(self, "_children", {}):
|
|
544
|
+
return self._children[fname]
|
|
512
545
|
val = self._data[fname]
|
|
513
546
|
return val.item() if is_scalar else val
|
|
514
547
|
|
|
@@ -519,6 +552,11 @@ class CModule:
|
|
|
519
552
|
field_info=field_info,
|
|
520
553
|
is_scalar=is_scalar,
|
|
521
554
|
):
|
|
555
|
+
if fname in getattr(self, "_children", {}):
|
|
556
|
+
arr = np.ascontiguousarray(value, dtype=self._children[fname].dtype)
|
|
557
|
+
self._children[fname] = arr
|
|
558
|
+
self._data[fname] = arr.ctypes.data
|
|
559
|
+
return
|
|
522
560
|
if is_scalar:
|
|
523
561
|
self._data[fname] = value
|
|
524
562
|
else:
|
|
@@ -200,10 +200,6 @@ def _parse_structs_with_pycparser(cdef: str) -> dict[str, StructSpec]:
|
|
|
200
200
|
for decl in struct.decls:
|
|
201
201
|
ctype, is_ptr, is_const, arr_len = _ctype_from_decl(decl.type)
|
|
202
202
|
base = base_type_from_ctype(ctype)
|
|
203
|
-
try:
|
|
204
|
-
numpy_dtype_for_base_type(base)
|
|
205
|
-
except TypeError:
|
|
206
|
-
continue
|
|
207
203
|
fields.append(
|
|
208
204
|
StructField(
|
|
209
205
|
name=decl.name,
|
|
@@ -311,7 +307,7 @@ def _parse_structs_regex(cdef: str) -> dict[str, StructSpec]:
|
|
|
311
307
|
if not line:
|
|
312
308
|
continue
|
|
313
309
|
line = re.sub(r"/\*.*?\*/", "", line).strip()
|
|
314
|
-
m_field = re.match(r"(
|
|
310
|
+
m_field = re.match(r"(.+?\*?)\s*([A-Za-z_]\w*)(\s*\[(\d+)\])?$", line)
|
|
315
311
|
if not m_field:
|
|
316
312
|
continue
|
|
317
313
|
raw_ctype = m_field.group(1).strip()
|
|
@@ -320,10 +316,6 @@ def _parse_structs_regex(cdef: str) -> dict[str, StructSpec]:
|
|
|
320
316
|
is_pointer = "*" in raw_ctype
|
|
321
317
|
is_const = "const" in raw_ctype
|
|
322
318
|
base = base_type_from_ctype(raw_ctype)
|
|
323
|
-
try:
|
|
324
|
-
numpy_dtype_for_base_type(base)
|
|
325
|
-
except TypeError:
|
|
326
|
-
continue
|
|
327
319
|
fields.append(
|
|
328
320
|
StructField(
|
|
329
321
|
name=fname,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|