[Python-Dev] Rename Include/internals/ to Include/pycore/
Eric Snow
ericsnowcurrently at gmail.com
Wed Oct 31 14:22:29 EDT 2018
On Sun, Oct 28, 2018 at 10:20 AM Victor Stinner <vstinner at redhat.com> wrote:
> Python C API has no strict separation between the 3 levels of API:
>
> * core: Py_BUILD_CORE define
> * stable: Py_LIMITED_API define (it has a value)
> * regular: no define
>
> IMHO the current design of header files is done backward: by default,
> everything is public. To exclude an API from core or stable, "#ifdef
> Py_BUILD_CORE" and "#ifndef Py_LIMITED_API" are used. This design
> caused issues in the past: functions, variables or something else
> exposed whereas they were supposed to be "private".
This is a great point.
> I propose a practical solution for that: Include/*.h files would only
> be be public API.
As we've already discussed, I'm entirely in favor of this. :) In
fact, I was thinking along those same lines when I originally created
"Include/internal", when working on the runtime state consolidation.
When you originally shared your idea with me (2 years ago?) it made
perfect sense. :)
> The "core" API would live in a new subdirectory:
> Include/pycore/*.h.
I'm mostly -0 on this. "pycore" is fine I suppose, but I think
"internal" is more obvious to people looking through the repo. I can
imagine folks getting confused by having "core" in the directory name.
> Moreover, files of this subdirectory would have
> the prefix "pycore_". For example, Include/objimpl.h would have a
> twin: Include/pycore/pycore_objimpl.h which extend the public API with
> "core" APIs.
I'm not sure why this is necessary. When I created Include/internal I
ran into some issues with relative includes. However, I solved them
by doing the following (at Benjamin's recommendation, IIRC): always
explicitly specify "internal/<...>.h" in includes, even in
Include/internal/*.h.
For example:
https://github.com/python/cpython/blob/master/Include/internal/pystate.h#L11
#include "internal/ceval.h"
Note that a few lines above in that file I include the public header file:
#include "pystate.h"
Taking this approach there were no issues with "relative" includes.
Incidentally, I originally tried to solve the problem of relative
includes with a prefix ("_" IIRC), but that proved to introduce other
issues. Switching to using the explicit "internal/" worked great and
was more clear.
> I also propose to automatically load the twin: Include/objimpl.h would
> load Include/pycore/pycore_objimpl.h if Py_BUILD_CORE is defined:
>
> #ifdef Py_BUILD_CORE
> # include "pycore/pycore_objimpl.h"
> #endif
During the runtime state consolidation I took a similar approach
initially, though at a less granular scale, which proved to be a
headache. At first I added Include/internal/Python.h and then tried
to conditionally include it in Include/Python.h. That ended up
confusing, problematic, and unnecessary. At Benjamin's suggestion I
switched to explicitly including "internal/<...>.h" in .c files (only
where necessary). The result is simpler and more clear, identifying
dependencies in source files more tightly. It's also a bit more
idiomatic for well-written C code.
Here's an example of what I did:
https://github.com/python/cpython/blob/master/Python/ceval.c#L13
#include "internal/pystate.h"
Your proposal is similar, though more granular. And I suppose it is
reasonable as a short-term step for moving internal API out of the
public header files. However, I agree with Benjamin that the ideal
would be to not have the public headers rely at all on the internal
ones. I realize that I somewhat introduced the problem when I added
the internal headers, so I certainly don't have a lot of room to ask
anything here. :) Regardless, an intermediate step of conditionally
including the private headers in the public ones might be okay if we
have a long-term plan on how to not include the private headers at
all. I'd be interested in discussing that.
FWIW, in the existing internal headers I include some of the public
header files. I don't recall if I did anything the other direction
(i.e. include internal headers conditionally in the public ones).
> Only in some rare cases, you would have to explicitly use: #include
> "pycore/pycore_pygetopt.h". This header is fully private, there is no
> public header in Include/pygetopt.h. Or maybe we should modify
> Include/Python.h to also include "pycore/pycore_pygetopt.h" if
> Py_BUILD_CORE is defined? Well, that's just a detail.
As noted above, I tried that and it didn't work out well.
> First milestone:
>
> * Create Include/pycore/
-0 (less clear)
> * Move Py_BUILD_CORE specific code into Include/pycore/pycore_*.h
+1
> * Automatically include pycore files from Include/*.h files (#ifdef Py_BUILD_CORE)
-0 (maybe okay as an intermediate fix)
> Second milestone:
>
> * Find a solution for Py_LIMITED_API :-)
+1 :)
-eric
More information about the Python-Dev
mailing list