The problem is that such “divergence” (unintentional or not) exists in the NumPy itself.
Nobody ask to do anything like this. Struct and ctypes modules have no support for complex types for years before v3.14. Also, the memoryview had no support for 'Zd' or 'Zf' before, nor now (try tolist() method, for exampl). Per SC decision, “proposals” for the struct module aren’t part of the PEP 3118. The PEP doesn’t specify how to add new format codes. What does NumPy here is not documented at all.
So, I don’t think this break anything in the Python ecosystem. Someone can add support for 'F' and 'D' types to interact with the stdlib via buffer protocol. Or ignore new capabilities of the stdlib.
I’m not sure, should we accept things like 'Zi'? PEP doesn’t tell us too much. As Tim said above, it’s not obvious even for 'Zd'. We have to ask NumPy (looking on the code or playing with API it offers like you did) what’s a “correct” interpretation of “whatever the next specifier is”.
BTW, what’s it’s memory layout? Like Annex G double complex? Like Py_complex or MSVC’s _Dcomplex? From sources it looks that npy_cdouble might be an alias for double _Complex or e.g. _Dcomplex. Different C types, in principle. The CPython’s struct, array and ctypes modules always assume memory representation, compatible with the C standard. For good or bad — it’s different from the NumPy, and that may warrant new type codes.
Well, playing more with the patch, proposed above — I find that it’s much more hard to support such “brain split” in practice. (And I’m not taking into account complications of docs.) So, I’m not ready to come with a solution along this line soon.
Reversion of my recent patches might be an alternative:
Though, the ctypes module also offers support for buffer protocol (undocumented) and one since v3.14 uses 'F' and 'D' codes. If we can treat this as a bug — I think we could easily fix that, see patch below.
ctypes patch
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 55eade1c830..83968e0c9c4 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -311,7 +311,7 @@ _ctypes_alloc_format_string_for_type(char code, int big_endian)
break;
}
- result = PyMem_Malloc(3);
+ result = PyMem_Malloc(4);
if (result == NULL) {
PyErr_NoMemory();
return NULL;
@@ -320,6 +320,7 @@ _ctypes_alloc_format_string_for_type(char code, int big_endian)
result[0] = big_endian ? '>' : '<';
result[1] = pep_code;
result[2] = '\0';
+ result[3] = '\0';
return result;
}
@@ -3098,7 +3099,22 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
view->len = self->b_size;
view->readonly = 0;
/* use default format character if not set */
- view->format = info->format ? info->format : "B";
+ if (!info->format) {
+ view->format = "B";
+ }
+ else {
+ view->format = info->format;
+ if (view->format[1] == 'F') {
+ view->format[1] = 'Z';
+ view->format[2] = 'f';
+ view->format[3] = '\0';
+ }
+ if (view->format[1] == 'D') {
+ view->format[1] = 'Z';
+ view->format[2] = 'd';
+ view->format[3] = '\0';
+ }
+ }
view->ndim = info->ndim;
view->shape = info->shape;
view->itemsize = item_info->size;
What do you think about this? CC @vstinner
But I believe, first we should ask SC to reconsider their position, no? Would you mind to open an issue?
I think that added support for 'e' format type could be kept for memoryview/array, despite nor NumPy docs, nor PEP specify anything about this. It seems NumPy uses same type code for export with the buffer protocol, so — probably we are safe here.