No need for that – the SC already voted. Just need to solve the practical issues now – but while solving them, I found some confusion and thought up a proposal to make.
I’ve been told that it looks like I’m throwing a little tantrum (and I honestly thank you for the feedback!). I think I found the cause for that: the SC’s requirement looks like an insignificant tweak, but I see it as an additional design constraint – and with it, I can’t find a solution that feels like a net win for API tier definition. Sadly, I can’t just decide I don’t care enough about the underscore.
Perhaps I am too nitpicky to be the expert on API tiers. I’d be happy to delegate or collaborate. But if I am to implement the PEP I do need a nitpick-level understanding of how things should be.
The practical issue is that to implement the PEP, I’ll need to change the docs and devguide definitions of the internal API tier. And if the underscore isn’t the “private” marker any more, what is? In other words:
how should users do that? I feel a duty to make this straightforward and obvious, but I always keep coming back to wanting to say “underscore=internal”. Here’s my thought process:
What could define a precise boundary between unstable & private?
- Availability in the headers? Doesn’t work, unfortunately: If a private function needs to be
static inline (or macro) for performance, it needs to be exposed. We can’t use #define/#include to opt in or out of the private tier. (It can work for other tiers though.)
- Docs? Docs are actually a bad way to define API tiers.
- In a volunteer-driven project, features are unfortunately often undocumented or underdocumented. They go out of date over time.
- What even is docs? Do PEPs count? HOWTOs? Source comments? Do I trawl through the whole docs for a note, or is the first entry in search enough? (Not trying to troll here – trying to find a way to make clauses like unless documented otherwise useful for a precise tier boundary)
- A definitive list (exported to the docs)? It works for Limited API, but it’s nowhere near perfect yet, and the checks for that list are quite a maintenance burden. Too much burden for the unstable tier, IMO.
- Should users look in the header file? That would technically work, but it’s ugly.
- (Should users check if the opt-in disables their function? I’ll stop listing bad brainstorming ideas now.)
- Name is the only usable marker I can see.
Yes, PyUnstable_ would work. Thanks, Spencer!
I subjectively find it ugly, but I don’t see other good solutions given the constraint. (I assume I can convince the SC to allow that rather than _PyUnstable with underscore – see below.)
I’m trying to make things work with the constraint, even though I don’t agree with it. Worse, the reasoning behind the constraint still doesn’t make sense to me. It doesn’t have to (the SC is there to ensure different viewpoints are represented, and I sure don’t have experience maintaining a giant monorepo) – but it sure would help if it made sense. So I’ll try prying further, even though I’m probably annoying everyone at this point.
The few functions with specific purposes point makes it unlikely that you’ll mix different “families” of unstable functions in a single file. To me, that’s what makes a .c-file-level opt-in enough. If you’re worried about introducing more unstable functions, your file might be too big.
I said this before, but: I see opting-in to unstable API as indication that you may need to revisit that file for future CPython versions. In that light, accidentally introducing other unstable functions still doesn’t seem like enough of a concern. They’re not dangerous, they just have ⅓ of the support time compared to public ones.
What is a big concern for me is that if we lose the “underscored=private” rule, users might accidentally introduce new private functions to their files, seeing that underscores are already used elsewhere (see the inability to opt-out of the private tier I mentioned above). That worries me a lot. I worry very much that people will read the opt-in #define as “now I can use underscored functions”. If they do, the PEP is a failure.
Um… that’s the bigger problem I’m trying to solve here! I’m trying to inch toward a world where that isn’t the case :)
And finally, I can’t resist adding some purely personal opinion.
I would love to have dead-simple “underscored=private” rule. You should be able to grep your 100GLOC codebase for \b_Py and pipe the result straight to Jira. You should be able to send a drive-by PR for removing _Py use, without any doubt about whether it’s fixing a bug.
We’re not in that perfect situation yet, but a big part of that is that we currently also use underscores for unstable API. The PEP was originally meant to strengthen the rule, not weaken it.