[Python-Dev] PEP 579 and PEP 580: refactoring C functions and methods

Petr Viktorin encukou at gmail.com
Wed Sep 12 20:26:47 EDT 2018

On 06/20/18 01:53, Jeroen Demeyer wrote:
> Hello,
> Let me present PEP 579 and PEP 580.
> PEP 579 is an informational meta-PEP, listing some of the issues with 
> functions/methods implemented in C. The idea is to create several PEPs 
> each fix some part of the issues mentioned in PEP 579.
> PEP 580 is a standards track PEP to introduce a new "C call" protocol, 
> which is an important part of PEP 579. In the reference implementation 
> (which is work in progress), this protocol will be used by built-in 
> functions and methods. However, it should be used by more classes in the 
> future.
> You find the texts at
> https://www.python.org/dev/peps/pep-0579
> https://www.python.org/dev/peps/pep-0580

I finally had time to read the PEPs carefully.

Overall, great work! PEP 580 does look complicated, but it's well 
thought out and addresses real problems.

I think the main advantage over the competing PEP 576 is that it's a 
better foundation for solving Cython (and other C-API users) and my PEP 
573 (module state access from methods).

With that, I do have some comments.

The reference to PEP 573 is premature. If PEP 580 is implemented then 
PEP 573 will build on top, and I don't plan to update PEP 573 before 
that. So, I think 580 should be independent. If you agree I can 
summarize rationale for "parent", as much as it concerns 580.

# Using tp_print

The tp_print gimmick is my biggest worry.
AFAIK there's no guarantee that a function pointer and Py_ssize_t are 
the same size. That makes the backwards-compatibility typedef in the 
implementation is quite worrying:
     typedef Py_ssize_t printfunc
I can see the benefit for backporting to earlier Python versions, and 
maybe that outweighs worries about exotic architectures, but the PEP 
should at least have more words on why this is not a problem.

# The C Call protocol

I really like the fact that, in the reference implementation, the flags 
are arranged in a way that allows a switch statement to select what to 
call. That should be noted, if only to explain why there's no guarantee 
of compatibility between Python versions.

# Descriptor behavior

I'd say "SHOULD" rather than "MUST" here. The section describes how to 
implement expected/reasonable behavior, but I see no need to limit that.

"if func supports the C call protocol, then func.__set__ must not be 
implemented." -- also, __delete__ should not be implemented, right?.

# Generic API functions

I'm a bit worried about PyCCall_FASTCALL's "kwds" argument accepting a 
dict, which is mutable. I wouldn't mind dropping that capability, but if 
it stays, we need to require that the callable promises to not modify it.

PyCCall_FASTCALL is not a macro, shouldn't it be named PyCCall_FastCall?

# C API functions

The function PyCFunction_GetFlags is, for better or worse, part of the 
stable ABI. We shouldn't just give up on it. I'm fine with documenting 
that it shouldn't be used, but for functions defined using 
PyCFunction_New etc. it should continue behaving as before.
One solution could be to preserve the "definition time" METH_* flags in 
the 0xFFF bits of cc_flags and use the other bits for CCALL_*.

# Stable ABI

The section should repeat that PyCFunction_ClsNew is added to the stable 
ABI (but nothing else).

More information about the Python-Dev mailing list