Hi,
I didn’t reply recently since I got overwhelmed by the discussion. I expected that the C API Working Group would take a decision, either accept or reject the PEP, rather than restarting the discussion (almost from scratch). The current PEP 757 design is the result of many months of work and tries to address most known issues. It’s not perfect, but it’s the best that Sergey and me could propose.
Sergey: I don’t understand why you accepted to add PyLongExport.value
and now you are moving backwards and argues against it. There are reasons why we added this member:
- We want to treat compact integers differently and having an
int64_t
is a nice trick to handle them. PyLong_Export() caller doesn’t have to attempt different APIs to check if it’s a “small” or “compatct” integer, it’s part of the API. - Maybe tomorrow, compact integers will not have an internal digits array and we want to avoid allocating memory in PyLong_Export() for best performance.
About preparing the structure for a potential future different export format: I really dislike this, I don’t want to waste memory until it’s needed (adding a reserved
member). If tomorrow PyLongExport
structure no longer fits, we should deprecate the PyLong_Export()
function and add a new one. It’s something very common in Python C API to deprecate functions and replace one function with another. Trying to make PyLong_Export()
“too future proof” would make it really hard to use in practice.
I has already been said, PyLong_Export() format relies on the “native layout” which is flexible enough to support any digits array. It sounds very unlikely that a new “bigint” implementation doesn’t fit with its design.
I also dislike changing PyLong_Export()
return value to return a kind which can be a new kind in the future. It sounds very unconvenient to have to support future hypothetical formats without knowing them in advance. It was proposed to kill the process in this case: I dislike that I don’t think that falling back on PyLong_AsNativeBytes()
makes sense here. If you already support PyLong_AsNativeBytes()
, just call it instead of PyLong_Export()
.
Last but not least, @encukou wants to remove the “always succeeds if it’s an integer” sentence. If tomorrow, Python internals evolve, maybe PyLong_Export()
has to allocate memory and so can fail. That’s why it’s paired with PyLong_FreeExport()
. I’m open to remove this sentence, I created a PR for that, but @skirpichev doesn’t seem to embrace it yet (at least, he didn’t approve it yet).
In short, I spent enough time on PEP 757, its API is not perfect but I don’t want to rewrite its API anymore. If you have question about why it’s designed this way, just ask. If you consider that the API is not good enough for your criteria, maybe we should just give up on PEP 757 abstraction and leaves the situation as it is: gmpy2 and SAGE use CPython internals and don’t support PyPy, and Python-FLINT uses an inefficient hex export (and so support PyPy). These projects are working well with the current code, so maybe it’s not worth it to provide a “better” API.
I propose to only make a single change to the current PEP 757: remove the following sentence.
This function always succeeds if obj is a Python
int
object or a subclass.