- Summary:
The PEP, or sometimes just the documentation, definitely requires
that features not requested shall be NULL.
The API would benefit from:
a. stored flags that tell you the actual structural
features.
b. requiring exporters to provide full information (e.g. strides =
{1}, format = "B") even when trivial.
It could and possibly should work this way in Python 4.0.
Nick thinks we could *allow* exporters to behave this way (PEP
change) in Python 3.x. Stefan thinks not, because "Perhaps there is
code that tests for shape==NULL to determine C-contiguity."
Jython exporters should return full information unconditionally from
the start: "any implementation that doesn't use the Py_buffer
struct directly
in a C-API should just always return a full buffer" (Stefan); "I
think that's the way Jython should go: *require*
that those fields be populated appropriately" (Nick).
- But what I now think is:
If the only problem really is "code that tests for
shape==NULL to determine C-contiguity", or makes similar deductions,
I agree that providing unasked-for information is safe. I
think the stipulation in PEP/documentation has some efficiency
value: on finding shape!=NULL the code has to do a more complicated
test, as inPyBuffer_IsContiguous(). I have the option to provide an
isContiguous that has the answer written down already, so the risk
is only from/to ported code. If it is only a risk to the efficiency
of ported code, I'm relaxed: I hesitate only to check that there's
no circumstance that logically requires nullity for correctness.
Whether it was safe that was the key question.
In the hypothetical Python 4.0 buffer API (and in Jython) where
feature flags are provided, the efficiency is still useful, but
complicated deductive logic in the consumer should be deprecated in
favour of (functions for) interrogating the flags.
An example illustrating the semantics would then be:
1. consumer requests a buffer, saying "I can cope with a strided
arrays" (PyBUF_STRIDED);
2. exporter provides a strides array, but in the feature flags
STRIDED=0, meaning "you don't need the strides array";
3. exporter (optionally) uses efficient, non-strided access.
I do not think that full provision by the exporter has to be
mandatory, as the discussion has gone on to suggest. I know
your experience is that you have often had to regenerate the missing
information to write generic code, but I think this does not
continue once you have the feature flags. An example would be:
1. consumer requests a buffer, saying "I can cope with a
N-dimensional but not strided arrays" (PyBUF_ND);
2. exporter sets strides=NULL, and the feature flag STRIDED=0;
3. exporter accesses the data, without reference to the strides
array, as it planned;
4. new generic code that respects the feature flag STRIDED=0, does
not reference the strides array;
5. old generic code, ignorant of the feature flags, finds the
strides=NULL and so does not dereference strides.
Insofar as it is not necessary, there is some efficiency in not
providing it. There would only be a problem with broken code that
both ignores the feature flag and uses the strides array unchecked.
But this code was always broken.
Really useful discussion this.
Jeff