Skip to content

Commit 3eba0a8

Browse files
committed
ParamValue UINT8+bytes path; expand python-paramlist tests
Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
1 parent 0436fc6 commit 3eba0a8

4 files changed

Lines changed: 51 additions & 2 deletions

File tree

src/python-nanobind/MIGRATION_STATUS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ Generated from the binding sources. The nanobind extension is `PyOpenImageIONano
99
| `py_roi.cpp` | <code>ROI</code><br>Free functions:<br><ul><li><code>union</code></li><li><code>intersection</code></li><li><code>get_roi</code></li><li><code>get_roi_full</code></li><li><code>set_roi</code></li><li><code>set_roi_full</code></li></ul> |
1010
| `py_typedesc.cpp` | <code>TypeDesc</code><br>Enums: <code>BASETYPE</code>, <code>AGGREGATE</code>, <code>VECSEMANTICS</code><br>Module <code>Type*</code> constants |
1111
| `py_imagespec.cpp` | <code>ImageSpec</code> (bound methods/properties, typed <code>attribute</code> / buffer paths via shared helpers). |
12+
| `py_paramvalue.cpp` | <code>ParamValue</code>, <code>ParamValueList</code><br>Enum: <code>Interp</code> |
1213

1314
## Migrated — partial (gaps or intentional deltas vs pybind)
1415

1516
| Source file | Migrated (vs pybind) | Missing or divergent (vs pybind) |
1617
| --- | --- | --- |
1718
| `py_oiio.cpp` (`_OpenImageIO` module) | <ul><li><code>attribute</code> (one-arg and typed)</li><li><code>get_int_attribute</code></li><li><code>get_float_attribute</code></li><li><code>get_string_attribute</code></li><li><code>getattribute</code></li><li><code>__version__</code></li></ul> | <ul><li><code>geterror</code></li><li><code>get_bytes_attribute</code></li><li>Module <code>set_colorspace</code> (helper taking <code>ImageSpec</code> — the instance method is on <code>ImageSpec</code> in nanobind)</li><li><code>set_colorspace_rec709_gamma</code></li><li><code>equivalent_colorspace</code></li><li><code>is_imageio_format_name</code></li><li><code>AutoStride</code></li><li><code>openimageio_version</code>, <code>VERSION</code>, <code>VERSION_STRING</code>, <code>VERSION_MAJOR</code>, <code>VERSION_MINOR</code>, <code>VERSION_PATCH</code>, <code>INTRO_STRING</code></li><li>Optional: stack traces when <code>OPENIMAGEIO_DEBUG_PYTHON</code> is set (<code>Sysutil</code>)</li><li><code>make_pyobject</code>: no pybind-style <code>debugfmt</code> when the type is unhandled (returns default quietly)</li></ul> |
18-
| `py_paramvalue.cpp` | Types: <code>ParamValue</code>, <code>ParamValueList</code><br>Enum: <code>Interp</code><br>Rest of the bound surface matches pybind. | <code>paramvalue_from_pyobject</code>: no pybind-style path for <code>UINT8</code> + <code>bytes</code> with <code>type.arraylen</code> (incl. inferred length from <code>bytes</code> size). |
1919
| `__init__.py` (package) | Env / DLL path setup, <code>from ._OpenImageIO import *</code>, version docstring. | <strong>TODO:</strong> Python CLI entry-point trampolines when the install layout matches the full wheel. |
2020

2121
---

src/python-nanobind/py_paramvalue.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,19 @@ paramvalue_from_pyobject(string_view name, TypeDesc type, int nvalues,
9696
converted.emplace_back(val);
9797
pv.init(name, type, nvalues, interp, converted.data());
9898
}
99+
} else if (type.basetype == TypeDesc::UINT8 && type.arraylen
100+
&& nb::isinstance<nb::bytes>(obj)) {
101+
TypeDesc t = type;
102+
nb::bytes b = nb::cast<nb::bytes>(obj);
103+
const std::string s(b.c_str(), b.size());
104+
if (t.arraylen < 0)
105+
t.arraylen = static_cast<int>(s.size()) / nvalues;
106+
if (t.arraylen * nvalues == static_cast<int>(s.size())) {
107+
std::vector<uint8_t> vals(
108+
reinterpret_cast<const uint8_t*>(s.data()),
109+
reinterpret_cast<const uint8_t*>(s.data()) + s.size());
110+
pv.init(name, t, nvalues, interp, vals.data());
111+
}
99112
} else if (type.basetype == TypeDesc::UINT8) {
100113
std::vector<uint8_t> vals;
101114
if (PyOpenImageIO::py_to_stdvector(vals, obj)

testsuite/python-paramlist/ref/out.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Testing individual ParamValue:
88
item g color (0.25, 0.5, 0.75)
99
item ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88]
1010
item bts uint8[10] [49 50 51 0 0 97 98 99 1 88]
11+
item u8unsized uint8[10] [49 50 51 52 53 54 55 56 57 48]
12+
item u8fix_n2 uint8[2] [ 97 98 99 100 101 102]
13+
item u8var_n2 uint8[4] [49 50 51 52 53 54 55 56]
1114

1215
Testing ParamValueList:
1316
pl length is 9

testsuite/python-paramlist/src/test_paramlist.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,41 @@ def print_param_list(pl: oiio.ParamValueList) :
5050
# Construct from numpy byte array
5151
pv = oiio.ParamValue("ucarr", "uint8[10]", numpy.array([49, 50, 51, 0, 0, 97, 98, 99, 1, 88], dtype='B'))
5252
print_param_value(pv)
53-
# Construct from bytes
53+
54+
# C++: paramvalue_from_pyobject UINT8 + Python bytes (pybind parity). Copy raw
55+
# bytes when type.arraylen is set, len(bytes) == arraylen*nvalues, and if
56+
# arraylen<0 (uint8[]), set arraylen = len(bytes)//nvalues first.
57+
58+
# Setup: fixed width uint8[10], single value — exercises bytes special case without inference.
5459
pv = oiio.ParamValue("bts", "uint8[10]", b'123\x00\x00abc\x01X')
60+
# Check: name/type/value match ref; bytes land as uint8[10] (10*1==10).
61+
print_param_value(pv)
62+
63+
# Setup: unsized uint8[], nvalues 1 — must infer arraylen 10 from len(bytes).
64+
pv = oiio.ParamValue("u8unsized", oiio.TypeDesc("uint8[]"), b"1234567890")
65+
# Check: type prints as uint8[10] (inferred) and payload matches the string bytes.
66+
print_param_value(pv)
67+
68+
# Setup: uint8[2] with nvalues=3, 6 bytes — fixed arraylen, multiple ParamValue "values".
69+
pv = oiio.ParamValue(
70+
"u8fix_n2",
71+
oiio.TypeDesc("uint8[2]"),
72+
3,
73+
oiio.Interp.CONSTANT,
74+
b"abcdef",
75+
)
76+
# Check: 2*3==6; same special-case path, no arraylen<0 branch.
77+
print_param_value(pv)
78+
79+
# Setup: unsized uint8[], nvalues=2, 8 bytes — infer arraylen=4, then 4*2==8.
80+
pv = oiio.ParamValue(
81+
"u8var_n2",
82+
oiio.TypeDesc("uint8[]"),
83+
2,
84+
oiio.Interp.CONSTANT,
85+
b"12345678",
86+
)
87+
# Check: type uint8[4] with 2 nvalues; exercises inference with nvalues>1.
5588
print_param_value(pv)
5689

5790
print ("")

0 commit comments

Comments
 (0)