So far RBufferOut return values, and FBuffer struct fields are 'str' on all the versions of Python. Python 3 distinguishes between 'str' (unicode strings), and 'bytes', with 'str' no more able to hold arbitrary data. For this reason, switch the return value of RBufferOut functions, and FBuffer struct fields to bytes on Python 3: while this is a potentially incompatibile change, this is the only way to handle safely sequences of arbitrary bytes. --- generator/python.ml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/generator/python.ml b/generator/python.ml index a70faec8c..bc5af528c 100644 --- a/generator/python.ml +++ b/generator/python.ml @@ -195,8 +195,13 @@ and generate_python_structs () = pr " goto err;\n"; pr " PyDict_SetItemString (dict, \"%s\", value);\n" name; | name, FBuffer -> + pr "#if PY_MAJOR_VERSION >= 3\n"; + pr " value = PyBytes_FromStringAndSize (%s->%s, %s->%s_len);\n" + typ name typ name; + pr "#else\n"; pr " value = guestfs_int_py_fromstringsize (%s->%s, %s->%s_len);\n" typ name typ name; + pr "#endif\n"; pr " if (value == NULL)\n"; pr " goto err;\n"; pr " PyDict_SetItemString (dict, \"%s\", value);\n" name; @@ -511,7 +516,11 @@ and generate_python_actions actions () = pr " guestfs_int_free_string_list (r);\n"; pr " if (py_r == NULL) goto out;\n"; | RBufferOut _ -> + pr "#if PY_MAJOR_VERSION >= 3\n"; + pr " py_r = PyBytes_FromStringAndSize (r, size);\n"; + pr "#else\n"; pr " py_r = guestfs_int_py_fromstringsize (r, size);\n"; + pr "#endif\n"; pr " free (r);\n"; pr " if (py_r == NULL) goto out;\n"; ); -- 2.20.1