PEP 432: Reduce typing in proposed API

- consistently abbreviate Config
- follow the Py*Object naming convention for Py*Config structs by
  dropping the underscore after the Py/_Py prefix
This commit is contained in:
Nick Coghlan 2013-01-15 22:28:45 +10:00
parent 8d83264979
commit 62a5df58bd
1 changed files with 51 additions and 46 deletions

View File

@ -61,7 +61,8 @@ environments).
To keep the implementation complexity under control, this PEP does *not*
propose wholesale changes to the way the interpreter state is accessed at
runtime, nor does it propose changes to the way subinterpreters are
created after the main interpreter has already been initialized. Changing
created after the main interpreter has already been initialized (beyond
any changes needed to make sure they continue working as expected). Changing
the order in which the existing initialization steps occur in order to make
the startup sequence easier to maintain is already a substantial change, and
attempting to make those other changes at the same time will make the
@ -239,7 +240,9 @@ be able to control the following aspects of the final interpreter state:
Note that this just covers settings that are currently configurable in some
manner when using the main CPython executable. While this PEP aims to make
adding additional configuration settings easier in the future, it
deliberately avoids adding any new settings of its own.
deliberately avoids adding any new settings of its own (except where such
additional settings arise naturally in the course of migrating existing
settings to the new structure).
Design Details
@ -280,7 +283,7 @@ Five distinct phases are proposed:
* ``Py_IsInitialized()`` returns ``0``
* The embedding application determines and applies the settings
required to complete the initialization process by calling
``Py_ReadConfiguration`` and ``Py_EndInitialization``.
``Py_ReadConfig`` and ``Py_EndInitialization``.
* Initialized:
@ -318,8 +321,8 @@ grained API, which allows the embedding application greater control
over the initialization process::
/* Phase 1: Pre-Initialization */
Py_CoreConfig core_config = Py_CoreConfig_INIT;
Py_Config config = Py_Config_INIT;
PyCoreConfig core_config = PyCoreConfig_INIT;
PyConfig config = PyConfig_INIT;
/* Easily control the core configuration */
core_config.ignore_environment = 1; /* Ignore environment variables */
core_config.use_hash_seed = 0; /* Full hash randomisation */
@ -327,13 +330,13 @@ over the initialization process::
/* Phase 2: Initialization */
/* Optionally preconfigure some settings here - they will then be
* used to derive other settings */
Py_ReadConfiguration(&config);
Py_ReadConfig(&config);
/* Can completely override derived settings here */
Py_EndInitialization(&config);
/* Phase 3: Initialized */
/* If an embedding application has no real concept of a main module
* it can leave the interpreter in this state indefinitely.
* Otherwise, it can launch __main__ via the Py_Run*AsMain functions.
* it can just stop the initialization process here.
* Alternatively, it can launch __main__ via the PyRun_*Main functions.
*/
@ -352,11 +355,13 @@ specific seed value for the randomised hashes, and if so, the specific value
for the seed (a seed value of zero disables randomised hashing). In addition,
due to the possible use of ``PYTHONHASHSEED`` in configuring the hash
randomisation, the question of whether or not to consider environment
variables must also be addressed early.
variables must also be addressed early. Finally, to support the CPython
build process, an option is offered to completely disable the import
system.
The proposed API for this step in the startup sequence is::
void Py_BeginInitialization(const Py_CoreConfig *config);
void Py_BeginInitialization(const PyCoreConfig *config);
Like Py_Initialize, this part of the new API treats initialization failures
as fatal errors. While that's still not particularly embedding friendly,
@ -364,27 +369,27 @@ the operations in this step *really* shouldn't be failing, and changing them
to return error codes instead of aborting would be an even larger task than
the one already being proposed.
The new ``Py_CoreConfig`` struct holds the settings required for preliminary
The new ``PyCoreConfig`` struct holds the settings required for preliminary
configuration::
/* Note: if changing anything in Py_CoreConfig, also update
* Py_CoreConfig_INIT */
/* Note: if changing anything in PyCoreConfig, also update
* PyCoreConfig_INIT */
typedef struct {
int ignore_environment; /* -E switch */
int use_hash_seed; /* PYTHONHASHSEED */
unsigned long hash_seed; /* PYTHONHASHSEED */
int _disable_importlib; /* Needed by freeze_importlib */
} Py_CoreConfig;
} PyCoreConfig;
#define Py_CoreConfig_INIT {0, -1, 0, 0}
#define PyCoreConfig_INIT {0, -1, 0, 0}
The core configuration settings pointer may be ``NULL``, in which case the
default values are ``ignore_environment = -1`` and ``use_hash_seed = -1``.
The ``Py_CoreConfig_INIT`` macro is designed to allow easy initialization
The ``PyCoreConfig_INIT`` macro is designed to allow easy initialization
of a struct instance with sensible defaults::
Py_CoreConfig core_config = Py_CoreConfig_INIT;
PyCoreConfig core_config = PyCoreConfig_INIT;
``ignore_environment`` controls the processing of all Python related
environment variables. If the flag is zero, then environment variables are
@ -498,7 +503,7 @@ The next step in the initialization sequence is to determine the full
settings needed to complete the process. No changes are made to the
interpreter state at this point. The core API for this step is::
int Py_ReadConfiguration(PyConfig *config);
int Py_ReadConfig(PyConfig *config);
The config argument should be a pointer to a config struct (which may be
a temporary one stored on the C stack). For any already configured value
@ -534,11 +539,11 @@ applied to the running interpreter until the ``Py_EndInitialization`` call
Supported configuration settings
--------------------------------
The new ``Py_Config`` struct holds the settings required to complete the
The new ``PyConfig`` struct holds the settings required to complete the
interpreter configuration. All fields are either pointers to Python
data types (not set == ``NULL``) or numeric flags (not set == ``-1``)::
/* Note: if changing anything in Py_Config, also update Py_Config_INIT */
/* Note: if changing anything in PyConfig, also update PyConfig_INIT */
typedef struct {
/* Argument processing */
PyListObject *raw_argv;
@ -611,30 +616,30 @@ data types (not set == ``NULL``) or numeric flags (not set == ``-1``)::
int show_banner; /* -q switch (inverted) */
int inspect_main; /* -i switch, PYTHONINSPECT */
} Py_Config;
} PyConfig;
/* Struct initialization is pretty ugly in C89. Avoiding this mess would
* be the most attractive aspect of using a PyDictObject* instead... */
#define _Py_ArgConfig_INIT NULL, NULL, NULL, NULL
#define _Py_LocationConfig_INIT NULL, NULL, NULL, NULL, NULL, NULL
#define _Py_SiteConfig_INIT -1, -1
#define _Py_ImportConfig_INIT -1, -1, NULL
#define _Py_StreamConfig_INIT -1, NULL, NULL, NULL, NULL, NULL, NULL
#define _Py_FilesystemConfig_INIT NULL
#define _Py_DebuggingConfig_INIT -1, -1, -1
#define _Py_CodeGenConfig_INIT -1, -1
#define _Py_SignalConfig_INIT -1
#define _Py_ImplicitConfig_INIT NULL
#define _Py_MainConfig_INIT -1, NULL, NULL, NULL, NULL, NULL, -1
#define _Py_InteractiveConfig_INIT NULL, -1, -1
#define _PyArgConfig_INIT NULL, NULL, NULL, NULL
#define _PyLocationConfig_INIT NULL, NULL, NULL, NULL, NULL, NULL
#define _PySiteConfig_INIT -1, -1
#define _PyImportConfig_INIT -1, -1, NULL
#define _PyStreamConfig_INIT -1, NULL, NULL, NULL, NULL, NULL, NULL
#define _PyFilesystemConfig_INIT NULL
#define _PyDebuggingConfig_INIT -1, -1, -1
#define _PyCodeGenConfig_INIT -1, -1
#define _PySignalConfig_INIT -1
#define _PyImplicitConfig_INIT NULL
#define _PyMainConfig_INIT -1, NULL, NULL, NULL, NULL, NULL, -1
#define _PyInteractiveConfig_INIT NULL, -1, -1
#define Py_Config_INIT {_Py_ArgConfig_INIT, _Py_LocationConfig_INIT,
_Py_SiteConfig_INIT, _Py_ImportConfig_INIT,
_Py_StreamConfig_INIT, _Py_FilesystemConfig_INIT,
_Py_DebuggingConfig_INIT, _Py_CodeGenConfig_INIT,
_Py_SignalConfig_INIT, _Py_ImplicitConfig_INIT,
_Py_MainConfig_INIT, _Py_InteractiveConfig_INIT}
#define PyConfig_INIT {_PyArgConfig_INIT, _PyLocationConfig_INIT,
_PySiteConfig_INIT, _PyImportConfig_INIT,
_PyStreamConfig_INIT, _PyFilesystemConfig_INIT,
_PyDebuggingConfig_INIT, _PyCodeGenConfig_INIT,
_PySignalConfig_INIT, _PyImplicitConfig_INIT,
_PyMainConfig_INIT, _PyInteractiveConfig_INIT}
<TBD: did I miss anything?>
@ -646,14 +651,14 @@ The final step in the initialization process is to actually put the
configuration settings into effect and finish bootstrapping the interpreter
up to full operation::
int Py_EndInitialization(const Py_Config *config);
int Py_EndInitialization(const PyConfig *config);
Like Py_ReadConfiguration, this call will raise an exception and report an
error return rather than exhibiting fatal errors if a problem is found with
the config data.
All configuration settings are required - the configuration struct
should always be passed through ``Py_ReadConfiguration()`` to ensure it
should always be passed through ``Py_ReadConfig()`` to ensure it
is fully populated.
After a successful call, ``Py_IsInitializing()`` will be false, while
@ -792,7 +797,7 @@ Internal Storage of Configuration Data
The interpreter state will be updated to include details of the configuration
settings supplied during initialization by extending the interpreter state
object with an embedded copy of the ``Py_CoreConfig`` and ``Py_Config``
object with an embedded copy of the ``PyCoreConfig`` and ``PyConfig``
structs.
For debugging purposes, the configuration settings will be exposed as
@ -834,7 +839,7 @@ Backwards Compatibility
-----------------------
Backwards compatibility will be preserved primarily by ensuring that
``Py_ReadConfiguration()`` interrogates all the previously defined
``Py_ReadConfig()`` interrogates all the previously defined
configuration settings stored in global variables and environment variables,
and that ``Py_EndInitialization()`` writes affected settings back to the
relevant locations.
@ -911,14 +916,14 @@ Open Questions
* Should there be ``Py_PreparingMain()`` and ``Py_RunningMain()`` query APIs?
* Should the answer to ``Py_IsInitialized()`` be exposed via the ``sys``
module?
* Is initialisation of the ``Py_Config`` struct too unwieldy to be
* Is initialisation of the ``PyConfig`` struct too unwieldy to be
maintainable? Would a Python dictionary be a better choice, despite
being harder to work with from C code?
* Would it be better to manage the flag variables in ``Py_Config`` as
* Would it be better to manage the flag variables in ``PyConfig`` as
Python integers or as "negative means false, positive means true, zero
means not set" so the struct can be initialized with a simple
``memset(&config, 0, sizeof(*config))``, eliminating the need to update
both Py_Config and Py_Config_INIT when adding new fields?
both PyConfig and PyConfig_INIT when adding new fields?
* The name of the new system Python executable is a bikeshed waiting to be
painted. The 3 options considered so far are ``spython``, ``pysystem``
and ``python-minimal``. The PEP text reflects my current preferred choice