I replied as best as I could, but there were a lot of places where “I don’t understand the question” or “none of the above” were what I would have preferred. Rather than just answering “other” to everything, I made a best attempt. I hope that doesn’t distort the result too much, although there are certainly cases where you could implement what I voted for and I’d hate it…
The biggest issue for me is that it’s hard to answer in the absence of information on how we’d get to the final state. For example, I voted for access via a distinct interface, but a lot depends on what that interface is, and whether it’s designed to make accessing internals feel like you’re doing something wrong (as opposed to just making a choice on whether you’re comfortable with using something unsupported).
Internal by default is unacceptable to me if it affects existing modules, which weren’t designed with that in mind. But as a long term goal with a viable transition plan, it might be reasonable. I wasn’t able to choose it even if I wanted to, without more details.
As for declaration locality, my real answer is “alongside the documentation that explains what the public API is”. If that’s a module docstring, then “at the top” makes sense. If it’s function/class docstrings, “at point of definition” is best. If it’s in a separate document, neither is ideal and you’re in effect duplicating information. Whatever is easier to ensure docs and code are kept in sync applies then. So I said “both” - but randomly mixing the two approaches in the same module is (obviously, to me) a really bad idea, so the option I voted for (“can be mixed”) implies more freedom than I think is acceptable in practice.
Package level visibility is the one where I had the worst case of “I don’t understand the question”. I want to substitute “project” for “package”, but the two concepts aren’t quite the same and I don’t know how that would affect my answers. But taking “package” as the best we can do, it still depends. I’d want something like an “internal” pkg.utils module to be directly accessible everywhere in pkg, but I wouldn’t want private support functions in pkg.cli to be usable in pkg.networking, for example. And unit tests are a whole other issue - having to jump through extra hoops to access the internal support function that you’re specifically testing seems like unnecessary complexity. I said “same-package modules can directly access each other’s internals” because I think the status quo is the best we can realistically hope for here (especially if we are considering backward compatibility). And even that doesn’t cover tests, so I’d extend it to “same-package and test modules can directly access internals”.
One key thing that drives my views here. Within a single project, code as written now - with direct reference to internal names from anywhere within the project - is working code. It’s not wrong for a project to access its own internals. It may be a nasty bit of technical debt that the project would like to fix, but it’s not the same as an external user calling an API that’s not declared as public and supported. Therefore, in my view, backward compatibility requires that we don’t break this working code without the usual deprecation process. That means that (for example) the combination of “private by default” and “internals should be module level scoped” is not allowed without a deprecation and transition cycle under Python’s current backward compatibility policy.
This is where I get stuck with the whole “I don’t understand the question” problem. Options are being presented as if they are all equal, and the four questions are presented as independent. But they aren’t, once you take things like the compatibility policy into account. So as it stands, the poll is hiding (not intentionally, I’m sure!) a lot of important nuances around feasibility and complexity.