From 331a6a56e9a9c72f3e4605987fabdaec72677702 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 27 May 2019 16:39:22 +0200 Subject: bpo-36763: Implement the PEP 587 (GH-13592) * Add a whole new documentation page: "Python Initialization Configuration" * PyWideStringList_Append() return type is now PyStatus, instead of int * PyInterpreterState_New() now calls PyConfig_Clear() if PyConfig_InitPythonConfig() fails. * Rename files: * Python/coreconfig.c => Python/initconfig.c * Include/cpython/coreconfig.h => Include/cpython/initconfig.h * Include/internal/: pycore_coreconfig.h => pycore_initconfig.h * Rename structures * _PyCoreConfig => PyConfig * _PyPreConfig => PyPreConfig * _PyInitError => PyStatus * _PyWstrList => PyWideStringList * Rename PyConfig fields: * use_module_search_paths => module_search_paths_set * module_search_path_env => pythonpath_env * Rename PyStatus field: _func => func * PyInterpreterState: rename core_config field to config * Rename macros and functions: * _PyCoreConfig_SetArgv() => PyConfig_SetBytesArgv() * _PyCoreConfig_SetWideArgv() => PyConfig_SetArgv() * _PyCoreConfig_DecodeLocale() => PyConfig_SetBytesString() * _PyInitError_Failed() => PyStatus_Exception() * _Py_INIT_ERROR_TYPE_xxx enums => _PyStatus_TYPE_xxx * _Py_UnixMain() => Py_BytesMain() * _Py_ExitInitError() => Py_ExitStatusException() * _Py_PreInitializeFromArgs() => Py_PreInitializeFromBytesArgs() * _Py_PreInitializeFromWideArgs() => Py_PreInitializeFromArgs() * _Py_PreInitialize() => Py_PreInitialize() * _Py_RunMain() => Py_RunMain() * _Py_InitializeFromConfig() => Py_InitializeFromConfig() * _Py_INIT_XXX() => _PyStatus_XXX() * _Py_INIT_FAILED() => _PyStatus_EXCEPTION() * Rename 'err' PyStatus variables to 'status' * Convert RUN_CODE() macro to config_run_code() static inline function * Remove functions: * _Py_InitializeFromArgs() * _Py_InitializeFromWideArgs() * _PyInterpreterState_GetCoreConfig() --- Doc/c-api/index.rst | 1 + Doc/c-api/init_config.rst | 1018 ++++++++ Doc/c-api/veryhigh.rst | 7 + Doc/whatsnew/3.8.rst | 55 + Include/Python.h | 2 +- Include/cpython/coreconfig.h | 436 ---- Include/cpython/initconfig.h | 429 ++++ Include/cpython/pylifecycle.h | 30 +- Include/cpython/pystate.h | 4 +- Include/internal/pycore_coreconfig.h | 163 -- Include/internal/pycore_initconfig.h | 168 ++ Include/internal/pycore_pathconfig.h | 20 +- Include/internal/pycore_pylifecycle.h | 38 +- Include/internal/pycore_pystate.h | 14 +- Lib/test/test_embed.py | 156 +- Makefile.pre.in | 10 +- .../C API/2019-05-27-12-25-25.bpo-36763.bHCA9j.rst | 1 + Modules/_io/_iomodule.c | 2 +- Modules/_io/iobase.c | 2 +- Modules/_testinternalcapi.c | 2 +- Modules/faulthandler.c | 10 +- Modules/getpath.c | 476 ++-- Modules/main.c | 101 +- Objects/bytearrayobject.c | 4 +- Objects/bytesobject.c | 4 +- Objects/exceptions.c | 24 +- Objects/listobject.c | 2 +- Objects/moduleobject.c | 4 +- Objects/object.c | 10 +- Objects/tupleobject.c | 2 +- Objects/unicodeobject.c | 62 +- PC/getpathp.c | 146 +- PCbuild/pythoncore.vcxproj | 6 +- PCbuild/pythoncore.vcxproj.filters | 18 +- Programs/_freeze_importlib.c | 34 +- Programs/_testembed.c | 420 ++-- Programs/python.c | 2 +- Python/bltinmodule.c | 2 +- Python/bootstrap_hash.c | 12 +- Python/compile.c | 4 +- Python/coreconfig.c | 2429 ------------------- Python/dynload_hpux.c | 2 +- Python/errors.c | 8 +- Python/frozenmain.c | 24 +- Python/import.c | 30 +- Python/initconfig.c | 2437 ++++++++++++++++++++ Python/pathconfig.c | 214 +- Python/preconfig.c | 235 +- Python/pylifecycle.c | 689 +++--- Python/pystate.c | 41 +- Python/pythonrun.c | 4 +- Python/sysmodule.c | 56 +- 52 files changed, 5567 insertions(+), 4503 deletions(-) create mode 100644 Doc/c-api/init_config.rst delete mode 100644 Include/cpython/coreconfig.h create mode 100644 Include/cpython/initconfig.h delete mode 100644 Include/internal/pycore_coreconfig.h create mode 100644 Include/internal/pycore_initconfig.h create mode 100644 Misc/NEWS.d/next/C API/2019-05-27-12-25-25.bpo-36763.bHCA9j.rst delete mode 100644 Python/coreconfig.c create mode 100644 Python/initconfig.c diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst index 3bfbaf4..9a8f150 100644 --- a/Doc/c-api/index.rst +++ b/Doc/c-api/index.rst @@ -21,6 +21,7 @@ document the API functions in detail. abstract.rst concrete.rst init.rst + init_config.rst memory.rst objimpl.rst apiabiversion.rst diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst new file mode 100644 index 0000000..0d94e6b --- /dev/null +++ b/Doc/c-api/init_config.rst @@ -0,0 +1,1018 @@ +.. highlight:: c + +.. _init-config: + +*********************************** +Python Initialization Configuration +*********************************** + +.. versionadded:: 3.8 + +Structures: + +* :c:type:`PyConfig` +* :c:type:`PyPreConfig` +* :c:type:`PyStatus` +* :c:type:`PyWideStringList` + +Functions: + +* :c:func:`PyConfig_Clear` +* :c:func:`PyConfig_InitIsolatedConfig` +* :c:func:`PyConfig_InitPythonConfig` +* :c:func:`PyConfig_Read` +* :c:func:`PyConfig_SetArgv` +* :c:func:`PyConfig_SetBytesArgv` +* :c:func:`PyConfig_SetBytesString` +* :c:func:`PyConfig_SetString` +* :c:func:`PyPreConfig_InitIsolatedConfig` +* :c:func:`PyPreConfig_InitPythonConfig` +* :c:func:`PyStatus_Error` +* :c:func:`PyStatus_Exception` +* :c:func:`PyStatus_Exit` +* :c:func:`PyStatus_IsError` +* :c:func:`PyStatus_IsExit` +* :c:func:`PyStatus_NoMemory` +* :c:func:`PyStatus_Ok` +* :c:func:`PyWideStringList_Append` +* :c:func:`PyWideStringList_Insert` +* :c:func:`Py_ExitStatusException` +* :c:func:`Py_InitializeFromConfig` +* :c:func:`Py_PreInitialize` +* :c:func:`Py_PreInitializeFromArgs` +* :c:func:`Py_PreInitializeFromBytesArgs` +* :c:func:`Py_RunMain` + +The preconfiguration (``PyPreConfig`` type) is stored in +``_PyRuntime.preconfig`` and the configuration (``PyConfig`` type) is stored in +``PyInterpreterState.config``. + +.. seealso:: + :pep:`587` "Python Initialization Configuration". + + +PyWideStringList +---------------- + +.. c:type:: PyWideStringList + + List of ``wchar_t*`` strings. + + If *length* is non-zero, *items* must be non-NULL and all strings must be + non-NULL. + + Methods: + + .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) + + Append *item* to *list*. + + Python must be preinitialized to call this function. + + .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item) + + Insert *item* into *list* at *index*. If *index* is greater than *list* + length, just append *item* to *list*. + + Python must be preinitialized to call this function. + + Structure fields: + + .. c:member:: Py_ssize_t length + + List length. + + .. c:member:: wchar_t** items + + List items. + +PyStatus +-------- + +.. c:type:: PyStatus + + Structure to store an initialization function status: success, error + or exit. + + For an error, it can store the C function name which created the error. + + Structure fields: + + .. c:member:: int exitcode + + Exit code. Argument passed to ``exit()``. + + .. c:member:: const char *err_msg + + Error message. + + .. c:member:: const char *func + + Name of the function which created an error, can be ``NULL``. + + Functions to create a status: + + .. c:function:: PyStatus PyStatus_Ok(void) + + Success. + + .. c:function:: PyStatus PyStatus_Error(const char *err_msg) + + Initialization error with a message. + + .. c:function:: PyStatus PyStatus_NoMemory(void) + + Memory allocation failure (out of memory). + + .. c:function:: PyStatus PyStatus_Exit(int exitcode) + + Exit Python with the specified exit code. + + Functions to handle a status: + + .. c:function:: int PyStatus_Exception(PyStatus status) + + Is the status an error or an exit? If true, the exception must be + handled; by calling :c:func:`Py_ExitStatusException` for example. + + .. c:function:: int PyStatus_IsError(PyStatus status) + + Is the result an error? + + .. c:function:: int PyStatus_IsExit(PyStatus status) + + Is the result an exit? + + .. c:function:: void Py_ExitStatusException(PyStatus status) + + Call ``exit(exitcode)`` if *status* is an exit. Print the error + message and exit with a non-zero exit code if *status* is an error. Must + only be called if ``PyStatus_Exception(status)`` is non-zero. + +.. note:: + Internally, Python uses macros which set ``PyStatus.func``, + whereas functions to create a status set ``func`` to ``NULL``. + +Example:: + + PyStatus alloc(void **ptr, size_t size) + { + *ptr = PyMem_RawMalloc(size); + if (*ptr == NULL) { + return PyStatus_NoMemory(); + } + return PyStatus_Ok(); + } + + int main(int argc, char **argv) + { + void *ptr; + PyStatus status = alloc(&ptr, 16); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + PyMem_Free(ptr); + return 0; + } + + +PyPreConfig +----------- + +.. c:type:: PyPreConfig + + Structure used to preinitialize Python: + + * Set the Python memory allocator + * Configure the LC_CTYPE locale + * Set the UTF-8 mode + + Function to initialize a preconfiguration: + + .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig) + + Initialize the preconfiguration with :ref:`Python Configuration + `. + + .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig) + + Initialize the preconfiguration with :ref:`Isolated Configuration + `. + + Structure fields: + + .. c:member:: int allocator + + Name of the memory allocator: + + * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators + (use defaults) + * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): default memory allocators + * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): default memory allocators with + debug hooks + * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): force usage of ``malloc()`` + * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of + ``malloc()`` with debug hooks + * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory + allocator ` + * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc + memory allocator ` with debug hooks + + ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` + are not supported if Python is configured using ``--without-pymalloc`` + + See :ref:`Memory Management `. + + .. c:member:: int configure_locale + + Set the LC_CTYPE locale to the user preferred locale? If equals to 0, set + :c:member:`coerce_c_locale` and :c:member:`coerce_c_locale_warn` to 0. + + .. c:member:: int coerce_c_locale + + If equals to 2, coerce the C locale; if equals to 1, read the LC_CTYPE + locale to decide if it should be coerced. + + .. c:member:: int coerce_c_locale_warn + If non-zero, emit a warning if the C locale is coerced. + + .. c:member:: int dev_mode + + See :c:member:`PyConfig.dev_mode`. + + .. c:member:: int isolated + + See :c:member:`PyConfig.isolated`. + + .. c:member:: int legacy_windows_fs_encoding (Windows only) + + If non-zero, disable UTF-8 Mode, set the Python filesystem encoding to + ``mbcs``, set the filesystem error handler to ``replace``. + + Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for + Windows specific code. + + .. c:member:: int parse_argv + + If non-zero, :c:func:`Py_PreInitializeFromArgs` and + :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the + same way the regular Python parses command line arguments: see + :ref:`Command Line Arguments `. + + .. c:member:: int use_environment + + See :c:member:`PyConfig.use_environment`. + + .. c:member:: int utf8_mode + + If non-zero, enable the UTF-8 mode. + +Preinitialization with PyPreConfig +---------------------------------- + +Functions to preinitialize Python: + +.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig) + + Preinitialize Python from *preconfig* preconfiguration. + +.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv) + + Preinitialize Python from *preconfig* preconfiguration and command line + arguments (bytes strings). + +.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv) + + Preinitialize Python from *preconfig* preconfiguration and command line + arguments (wide strings). + +The caller is responsible to handle exceptions (error or exit) using +:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`. + +For :ref:`Python Configuration ` +(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with +command line arguments, the command line arguments must also be passed to +preinitialize Python, since they have an effect on the pre-configuration +like encodings. For example, the :option:`-X` ``utf8`` command line option +enables the UTF-8 Mode. + +``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and +before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator. +It can be called before :c:func:`Py_PreInitialize` if +:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``. + +Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be +used before Python preinitialization, whereas calling directly ``malloc()`` and +``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called before +the preinitialization. + +Example using the preinitialization to enable the UTF-8 Mode:: + + PyPreConfig preconfig; + PyPreConfig_InitPythonConfig(&preconfig); + + preconfig.utf8_mode = 1; + + PyStatus status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + /* at this point, Python will speak UTF-8 */ + + Py_Initialize(); + /* ... use Python API here ... */ + Py_Finalize(); + + +PyConfig +-------- + +.. c:type:: PyConfig + + Structure containing most parameters to configure Python. + + Structure methods: + + .. c:function:: PyStatus PyConfig_InitPythonConfig(PyConfig *config) + + Initialize configuration with :ref:`Python Configuration + `. + + .. c:function:: PyStatus PyConfig_InitIsolatedConfig(PyConfig *config) + + Initialize configuration with :ref:`Isolated Configuration + `. + + .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str) + + Copy the wide character string *str* into ``*config_str``. + + Preinitialize Python if needed. + + .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str) + + Decode *str* using ``Py_DecodeLocale()`` and set the result into ``*config_str``. + + Preinitialize Python if needed. + + .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv) + + Set command line arguments from wide character strings. + + Preinitialize Python if needed. + + .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv) + + Set command line arguments: decode bytes using :c:func:`Py_DecodeLocale`. + + Preinitialize Python if needed. + + .. c:function:: PyStatus PyConfig_Read(PyConfig *config) + + Read all Python configuration. + + Fields which are already initialized are left unchanged. + + Preinitialize Python if needed. + + .. c:function:: void PyConfig_Clear(PyConfig *config) + + Release configuration memory. + + Most ``PyConfig`` methods preinitialize Python if needed. In that case, the + Python preinitialization configuration in based on the :c:type:`PyConfig`. + If configuration fields which are in common with :c:type:`PyPreConfig` are + tuned, they must be set before calling a :c:type:`PyConfig` method: + + * :c:member:`~PyConfig.dev_mode` + * :c:member:`~PyConfig.isolated` + * :c:member:`~PyConfig.parse_argv` + * :c:member:`~PyConfig.use_environment` + + Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv` + is used, this method must be called first, before other methods, since the + preinitialization configuration depends on command line arguments (if + :c:member:`parse_argv` is non-zero). + + The caller of these methods is responsible to handle exceptions (error or + exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``. + + Structure fields: + + .. c:member:: PyWideStringList argv + + Command line arguments, :data:`sys.argv`. See + :c:member:`~PyConfig.parse_argv` to parse :c:member:`~PyConfig.argv` the + same way the regular Python parses Python command line arguments. If + :c:member:`~PyConfig.argv` is empty, an empty string is added to ensure + that :data:`sys.argv` always exists and is never empty. + + .. c:member:: wchar_t* base_exec_prefix + + :data:`sys.base_exec_prefix`. + + .. c:member:: wchar_t* base_prefix + + :data:`sys.base_prefix`. + + .. c:member:: int buffered_stdio + + If equals to 0, enable unbuffered mode, making the stdout and stderr + streams unbuffered. + + stdin is always opened in buffered mode. + + .. c:member:: int bytes_warning + + If equals to 1, issue a warning when comparing :class:`bytes` or + :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with + :class:`int`. If equal or greater to 2, raise a :exc:`BytesWarning` + exception. + + .. c:member:: wchar_t* check_hash_pycs_mode + + Control the validation behavior of hash-based ``.pyc`` files (see + :pep:`552`): :option:`--check-hash-based-pycs` command line option value. + + Valid values: ``always``, ``never`` and ``default``. + + The default value is: ``default``. + + .. c:member:: int configure_c_stdio + + If non-zero, configure C standard streams (``stdio``, ``stdout``, + ``stdout``). For example, set their mode to ``O_BINARY`` on Windows. + + .. c:member:: int dev_mode + + Development mode: see :option:`-X` ``dev``. + + .. c:member:: int dump_refs + + If non-zero, dump all objects which are still alive at exit. + + Require a debug build of Python (``Py_REF_DEBUG`` macro must be defined). + + .. c:member:: wchar_t* exec_prefix + + :data:`sys.exec_prefix`. + + .. c:member:: wchar_t* executable + + :data:`sys.executable`. + + .. c:member:: int faulthandler + + If non-zero, call :func:`faulthandler.enable`. + + .. c:member:: wchar_t* filesystem_encoding + + Filesystem encoding, :func:`sys.getfilesystemencoding`. + + .. c:member:: wchar_t* filesystem_errors + + Filesystem encoding errors, :func:`sys.getfilesystemencodeerrors`. + + .. c:member:: unsigned long hash_seed + .. c:member:: int use_hash_seed + + Randomized hash function seed. + + If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly + at Pythonstartup, and :c:member:`~PyConfig.hash_seed` is ignored. + + .. c:member:: wchar_t* home + + Python home directory. + + .. c:member:: int import_time + + If non-zero, profile import time. + + .. c:member:: int inspect + + Enter interactive mode after executing a script or a command. + + .. c:member:: int install_signal_handlers + + Install signal handlers? + + .. c:member:: int interactive + + Interactive mode. + + .. c:member:: int isolated + + If greater than 0, enable isolated mode: + + * :data:`sys.path` contains neither the script's directory (computed from + ``argv[0]`` or the current directory) nor the user's site-packages + directory. + * Python REPL doesn't import :mod:`readline` nor enable default readline + configuration on interactive prompts. + * Set :c:member:`~PyConfig.use_environment` and + :c:member:`~PyConfig.user_site_directory` to 0. + + .. c:member:: int legacy_windows_stdio + + If non-zero, use :class:`io.FileIO` instead of + :class:`io.WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout` + and :data:`sys.stderr`. + + Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for + Windows specific code. + + .. c:member:: int malloc_stats + + If non-zero, dump statistics on :ref:`Python pymalloc memory allocator + ` at exit. + + The option is ignored if Python is built using ``--without-pymalloc``. + + .. c:member:: wchar_t* pythonpath_env + + Module search paths as a string separated by ``DELIM`` + (:data:`os.path.pathsep`). + + Initialized from :envvar:`PYTHONPATH` environment variable value by + default. + + .. c:member:: PyWideStringList module_search_paths + .. c:member:: int module_search_paths_set + + :data:`sys.path`. If :c:member:`~PyConfig.module_search_paths_set` is + equal to 0, the :c:member:`~PyConfig.module_search_paths` is overridden + by the function computing the :ref:`Path Configuration + `. + + .. c:member:: int optimization_level + + Compilation optimization level: + + * 0: Peephole optimizer (and ``__debug__`` is set to ``True``) + * 1: Remove assertions, set ``__debug__`` to ``False`` + * 2: Strip docstrings + + .. c:member:: int parse_argv + + If non-zero, parse :c:member:`~PyConfig.argv` the same way the regular + Python command line arguments, and strip Python arguments from + :c:member:`~PyConfig.argv`: see :ref:`Command Line Arguments + `. + + .. c:member:: int parser_debug + + If non-zero, turn on parser debugging output (for expert only, depending + on compilation options). + + .. c:member:: int pathconfig_warnings + + If equal to 0, suppress warnings when computing the path configuration + (Unix only, Windows does not log any warning). Otherwise, warnings are + written into ``stderr``. + + .. c:member:: wchar_t* prefix + + :data:`sys.prefix`. + + .. c:member:: wchar_t* program_name + + Program name. + + .. c:member:: wchar_t* pycache_prefix + + ``.pyc`` cache prefix. + + .. c:member:: int quiet + + Quiet mode. For example, don't display the copyright and version messages + even in interactive mode. + + .. c:member:: wchar_t* run_command + + ``python3 -c COMMAND`` argument. + + .. c:member:: wchar_t* run_filename + + ``python3 FILENAME`` argument. + + .. c:member:: wchar_t* run_module + + ``python3 -m MODULE`` argument. + + .. c:member:: int show_alloc_count + + Show allocation counts at exit? + + Need a special Python build with ``COUNT_ALLOCS`` macro defined. + + .. c:member:: int show_ref_count + + Show total reference count at exit? + + Need a debug build of Python (``Py_REF_DEBUG`` macro must be defined). + + .. c:member:: int site_import + + Import the :mod:`site` module at startup? + + .. c:member:: int skip_source_first_line + + Skip the first line of the source? + + .. c:member:: wchar_t* stdio_encoding + .. c:member:: wchar_t* stdio_errors + + Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and + :data:`sys.stderr`. + + .. c:member:: int tracemalloc + + If non-zero, call :func:`tracemalloc.start`. + + .. c:member:: int use_environment + + If greater than 0, use :ref:`environment variables `. + + .. c:member:: int user_site_directory + + If non-zero, add user site directory to :data:`sys.path`. + + .. c:member:: int verbose + + If non-zero, enable verbose mode. + + .. c:member:: PyWideStringList warnoptions + + Options of the :mod:`warnings` module to build warnings filters. + + .. c:member:: int write_bytecode + + If non-zero, write ``.pyc`` files. + + .. c:member:: PyWideStringList xoptions + + :data:`sys._xoptions`. + +If ``parse_argv`` is non-zero, ``argv`` arguments are parsed the same +way the regular Python parses command line arguments, and Python +arguments are stripped from ``argv``: see :ref:`Command Line Arguments +`. + +The ``xoptions`` options are parsed to set other options: see :option:`-X` +option. + + +Initialization with PyConfig +---------------------------- + +Function to initialize Python: + +.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config) + + Initialize Python from *config* configuration. + +The caller is responsible to handle exceptions (error or exit) using +:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`. + +``PyImport_FrozenModules``, ``PyImport_AppendInittab()`` or +``PyImport_ExtendInittab()`` is used: they must be set or called after Python +preinitialization and before the Python initialization. + +Example setting the program name:: + + void init_python(void) + { + PyStatus status; + PyConfig config; + + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + goto fail; + } + + /* Set the program name. Implicitly preinitialize Python. */ + status = PyConfig_SetString(&config, &config.program_name, + L"/path/to/my_program"); + if (PyStatus_Exception(status)) { + goto fail; + } + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto fail; + } + PyConfig_Clear(&config); + return; + + fail: + PyConfig_Clear(&config); + Py_ExitStatusException(status); + } + +More complete example modifying the default configuration, read the +configuration, and then override some parameters:: + + PyStatus init_python(const char *program_name) + { + PyStatus status; + PyConfig config; + + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + goto done; + } + + /* Set the program name before reading the configuraton + (decode byte string from the locale encoding). + + Implicitly preinitialize Python. */ + status = PyConfig_SetBytesString(&config, &config.program_name, + program_name); + if (PyStatus_Exception(status)) { + goto done; + } + + /* Read all configuration at once */ + status = PyConfig_Read(&config); + if (PyStatus_Exception(status)) { + goto done; + } + + /* Append our custom search path to sys.path */ + status = PyWideStringList_Append(&config.module_search_paths, + L"/path/to/more/modules"); + if (PyStatus_Exception(status)) { + goto done; + } + + /* Override executable computed by PyConfig_Read() */ + status = PyConfig_SetString(&config, &config.executable, + L"/path/to/my_executable"); + if (PyStatus_Exception(status)) { + goto done; + } + + status = Py_InitializeFromConfig(&config); + + done: + PyConfig_Clear(&config); + return status; + } + + +.. _init-isolated-conf: + +Isolated Configuration +---------------------- + +:c:func:`PyPreConfig_InitIsolatedConfig` and +:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to +isolate Python from the system. For example, to embed Python into an +application. + +This configuration ignores global configuration variables, environments +variables and command line arguments (:c:member:`PyConfig.argv` is not parsed). +The C standard streams (ex: ``stdout``) and the LC_CTYPE locale are left +unchanged by default. + +Configuration files are still used with this configuration. Set the +:ref:`Path Configuration ` ("output fields") to ignore these +configuration files and avoid the function computing the default path +configuration. + + +.. _init-python-config: + +Python Configuration +-------------------- + +:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig` +functions create a configuration to build a customized Python which behaves as +the regular Python. + +Environments variables and command line arguments are used to configure +Python, whereas global configuration variables are ignored. + +This function enables C locale coercion (:pep:`538`) and UTF-8 Mode +(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and +:envvar:`PYTHONCOERCECLOCALE` environment variables. + +Example of customized Python always running in isolated mode:: + + int main(int argc, char **argv) + { + PyConfig config; + PyStatus status; + + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + goto fail; + } + + config.isolated = 1; + + /* Decode command line arguments. + Implicitly preinitialize Python (in isolated mode). */ + status = PyConfig_SetBytesArgv(&config, argc, argv); + if (PyStatus_Exception(status)) { + goto fail; + } + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto fail; + } + PyConfig_Clear(&config); + + return Py_RunMain(); + + fail: + PyConfig_Clear(&config); + if (PyStatus_IsExit(status)) { + return status.exitcode; + } + /* Display the error message and exit the process with + non-zero exit code */ + Py_ExitStatusException(status); + } + + +.. _init-path-config: + +Path Configuration +------------------ + +:c:type:`PyConfig` contains multiple fields for the path configuration: + +* Path configuration input fields: + + * :c:member:`PyConfig.home` + * :c:member:`PyConfig.pythonpath_env` + * :c:member:`PyConfig.pathconfig_warnings` + +* Path configuration output fields: + + * :c:member:`PyConfig.exec_prefix` + * :c:member:`PyConfig.executable` + * :c:member:`PyConfig.prefix` + * :c:member:`PyConfig.module_search_paths_set`, + :c:member:`PyConfig.module_search_paths` + +If at least one "output field" is not set, Python computes the path +configuration to fill unset fields. If +:c:member:`~PyConfig.module_search_paths_set` is equal to 0, +:c:member:`~PyConfig.module_search_paths` is overriden and +:c:member:`~PyConfig.module_search_paths_set` is set to 1. + +It is possible to completely ignore the function computing the default +path configuration by setting explicitly all path configuration output +fields listed above. A string is considered as set even if it is non-empty. +``module_search_paths`` is considered as set if +``module_search_paths_set`` is set to 1. In this case, path +configuration input fields are ignored as well. + +Set :c:member:`~PyConfig.pathconfig_warnings` to 0 to suppress warnings when +computing the path configuration (Unix only, Windows does not log any warning). + +If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix` +fields are not set, they inherit their value from :c:member:`~PyConfig.prefix` +and :c:member:`~PyConfig.exec_prefix` respectively. + +:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`: + +* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a + ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to + :data:`sys.path`. +* If :c:member:`~PyConfig.isolated` is zero: + + * If :c:member:`~PyConfig.run_module` is set, prepend the current directory + to :data:`sys.path`. Do nothing if the current directory cannot be read. + * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the + filename to :data:`sys.path`. + * Otherwise, prepend an empty string to :data:`sys.path`. + +If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be +modified by the :mod:`site` module. If +:c:member:`~PyConfig.user_site_directory` is non-zero and the user's +site-package directory exists, the :mod:`site` module appends the user's +site-package directory to :data:`sys.path`. + +The following configuration files are used by the path configuration: + +* ``pyvenv.cfg`` +* ``python._pth`` (Windows only) +* ``pybuilddir.txt`` (Unix only) + + +Py_RunMain() +------------ + +.. c:function:: int Py_RunMain(void) + + Execute the command (:c:member:`PyConfig.run_command`), the script + (:c:member:`PyConfig.run_filename`) or the module + (:c:member:`PyConfig.run_module`) specified on the command line or in the + configuration. + + By default and when if :option:`-i` option is used, run the REPL. + + Finally, finalizes Python and returns an exit status that can be passed to + the ``exit()`` function. + +See :ref:`Python Configuration ` for an example of +customized Python always running in isolated mode using +:c:func:`Py_RunMain`. + + +Multi-Phase Initialization Private Provisional API +-------------------------------------------------- + +This section is a private provisional API introducing multi-phase +initialization, the core feature of the :pep:`432`: + +* "Core" initialization phase, "bare minimum Python": + + * Builtin types; + * Builtin exceptions; + * Builtin and frozen modules; + * The :mod:`sys` module is only partially initialized + (ex: :data:`sys.path` doesn't exist yet); + +* "Main" initialization phase, Python is fully initialized: + + * Install and configure :mod:`importlib`; + * Apply the :ref:`Path Configuration `; + * Install signal handlers; + * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout` + and :data:`sys.path`); + * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`; + * Import the :mod:`site` module; + * etc. + +Private provisional API: + +* :c:member:`PyConfig._init_main`: if set to 0, + :c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase. + +.. c:function:: PyStatus _Py_InitializeMain(void) + + Move to the "Main" initialization phase, finish the Python initialization. + +No module is imported during the "Core" phase and the ``importlib`` module is +not configured: the :ref:`Path Configuration ` is only +applied during the "Main" phase. It may allow to customize Python in Python to +override or tune the :ref:`Path Configuration `, maybe +install a custom sys.meta_path importer or an import hook, etc. + +It may become possible to compute the :ref:`Path Configuration +` in Python, after the Core phase and before the Main phase, +which is one of the :pep:`432` motivation. + +The "Core" phase is not properly defined: what should be and what should +not be available at this phase is not specified yet. The API is marked +as private and provisional: the API can be modified or even be removed +anytime until a proper public API is designed. + +Example running Python code between "Core" and "Main" initialization +phases:: + + void init_python(void) + { + PyStatus status; + PyConfig config; + + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); + } + + config._init_main = 0; + + /* ... customize 'config' configuration ... */ + + status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + /* Use sys.stderr because sys.stdout is only created + by _Py_InitializeMain() */ + int res = PyRun_SimpleString( + "import sys; " + "print('Run Python code before _Py_InitializeMain', " + "file=sys.stderr)"); + if (res < 0) { + exit(1); + } + + /* ... put more configuration code here ... */ + + status = _Py_InitializeMain(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + } diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index a7ff08c..3fe0ae4 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -42,6 +42,13 @@ the same library that the Python runtime is using. ``Py_InspectFlag`` is not set. +.. c:function:: int Py_BytesMain(int argc, char **argv) + + Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings. + + .. versionadded:: 3.8 + + .. c:function:: int PyRun_AnyFile(FILE *fp, const char *filename) This is a simplified interface to :c:func:`PyRun_AnyFileExFlags` below, leaving diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 1180469..6102d8c 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -182,6 +182,61 @@ Would print ``x*9 + 15=42``. (Contributed by Eric V. Smith and Larry Hastings in :issue:`36817`.) +PEP 587: Python Initialization Configuration +-------------------------------------------- + +The :pep:`587` adds a new C API to configure the Python Initialization +providing finer control on the whole configuration and better error reporting. + +New structures: + +* :c:type:`PyConfig` +* :c:type:`PyPreConfig` +* :c:type:`PyStatus` +* :c:type:`PyWideStringList` + +New functions: + +* :c:func:`PyConfig_Clear` +* :c:func:`PyConfig_InitIsolatedConfig` +* :c:func:`PyConfig_InitPythonConfig` +* :c:func:`PyConfig_Read` +* :c:func:`PyConfig_SetArgv` +* :c:func:`PyConfig_SetBytesArgv` +* :c:func:`PyConfig_SetBytesString` +* :c:func:`PyConfig_SetString` +* :c:func:`PyPreConfig_InitIsolatedConfig` +* :c:func:`PyPreConfig_InitPythonConfig` +* :c:func:`PyStatus_Error` +* :c:func:`PyStatus_Exception` +* :c:func:`PyStatus_Exit` +* :c:func:`PyStatus_IsError` +* :c:func:`PyStatus_IsExit` +* :c:func:`PyStatus_NoMemory` +* :c:func:`PyStatus_Ok` +* :c:func:`PyWideStringList_Append` +* :c:func:`PyWideStringList_Insert` +* :c:func:`Py_BytesMain` +* :c:func:`Py_ExitStatusException` +* :c:func:`Py_InitializeFromConfig` +* :c:func:`Py_PreInitialize` +* :c:func:`Py_PreInitializeFromArgs` +* :c:func:`Py_PreInitializeFromBytesArgs` +* :c:func:`Py_RunMain` + +This PEP also adds ``_PyRuntimeState.preconfig`` (:c:type:`PyPreConfig` type) +and ``PyInterpreterState.config`` (:c:type:`PyConfig` type) fields to these +internal structures. ``PyInterpreterState.config`` becomes the new +reference configuration, replacing global configuration variables and +other private variables. + +See :ref:`Python Initialization Configuration ` for the +documentation. + +See :pep:`587` for a full description. + +(Contributed by Victor Stinner in :issue:`36763`.) + Other Language Changes ====================== diff --git a/Include/Python.h b/Include/Python.h index 17ad5b3..d6e5b13 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -129,7 +129,7 @@ #include "codecs.h" #include "pyerrors.h" -#include "cpython/coreconfig.h" +#include "cpython/initconfig.h" #include "pystate.h" #include "context.h" diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h deleted file mode 100644 index ef5fde2..0000000 --- a/Include/cpython/coreconfig.h +++ /dev/null @@ -1,436 +0,0 @@ -#ifndef Py_PYCORECONFIG_H -#define Py_PYCORECONFIG_H -#ifndef Py_LIMITED_API -#ifdef __cplusplus -extern "C" { -#endif - -/* --- _PyInitError ----------------------------------------------- */ - -typedef struct { - enum { - _Py_INIT_ERR_TYPE_OK=0, - _Py_INIT_ERR_TYPE_ERROR=1, - _Py_INIT_ERR_TYPE_EXIT=2 - } _type; - const char *_func; - const char *err_msg; - int exitcode; -} _PyInitError; - -PyAPI_FUNC(_PyInitError) _PyInitError_Ok(void); -PyAPI_FUNC(_PyInitError) _PyInitError_Error(const char *err_msg); -PyAPI_FUNC(_PyInitError) _PyInitError_NoMemory(void); -PyAPI_FUNC(_PyInitError) _PyInitError_Exit(int exitcode); -PyAPI_FUNC(int) _PyInitError_IsError(_PyInitError err); -PyAPI_FUNC(int) _PyInitError_IsExit(_PyInitError err); -PyAPI_FUNC(int) _PyInitError_Failed(_PyInitError err); - -/* --- _PyWstrList ------------------------------------------------ */ - -typedef struct { - /* If length is greater than zero, items must be non-NULL - and all items strings must be non-NULL */ - Py_ssize_t length; - wchar_t **items; -} _PyWstrList; - - -/* --- _PyPreConfig ----------------------------------------------- */ - -#define _Py_CONFIG_VERSION 1 - -typedef enum { - /* Py_Initialize() API: backward compatibility with Python 3.6 and 3.7 */ - _PyConfig_INIT_COMPAT = 1, - _PyConfig_INIT_PYTHON = 2, - _PyConfig_INIT_ISOLATED = 3 -} _PyConfigInitEnum; - - -typedef struct { - int _config_version; /* Internal configuration version, - used for ABI compatibility */ - int _config_init; /* _PyConfigInitEnum value */ - - /* Parse _Py_PreInitializeFromArgs() arguments? - See _PyCoreConfig.parse_argv */ - int parse_argv; - - /* If greater than 0, enable isolated mode: sys.path contains - neither the script's directory nor the user's site-packages directory. - - Set to 1 by the -I command line option. If set to -1 (default), inherit - Py_IsolatedFlag value. */ - int isolated; - - /* If greater than 0: use environment variables. - Set to 0 by -E command line option. If set to -1 (default), it is - set to !Py_IgnoreEnvironmentFlag. */ - int use_environment; - - /* Set the LC_CTYPE locale to the user preferred locale? If equals to 0, - set coerce_c_locale and coerce_c_locale_warn to 0. */ - int configure_locale; - - /* Coerce the LC_CTYPE locale if it's equal to "C"? (PEP 538) - - Set to 0 by PYTHONCOERCECLOCALE=0. Set to 1 by PYTHONCOERCECLOCALE=1. - Set to 2 if the user preferred LC_CTYPE locale is "C". - - If it is equal to 1, LC_CTYPE locale is read to decide it it should be - coerced or not (ex: PYTHONCOERCECLOCALE=1). Internally, it is set to 2 - if the LC_CTYPE locale must be coerced. - - Disable by default (set to 0). Set it to -1 to let Python decides if it - should be enabled or not. */ - int coerce_c_locale; - - /* Emit a warning if the LC_CTYPE locale is coerced? - - Set to 1 by PYTHONCOERCECLOCALE=warn. - - Disable by default (set to 0). Set it to -1 to let Python decides if it - should be enabled or not. */ - int coerce_c_locale_warn; - -#ifdef MS_WINDOWS - /* If greater than 1, use the "mbcs" encoding instead of the UTF-8 - encoding for the filesystem encoding. - - Set to 1 if the PYTHONLEGACYWINDOWSFSENCODING environment variable is - set to a non-empty string. If set to -1 (default), inherit - Py_LegacyWindowsFSEncodingFlag value. - - See PEP 529 for more details. */ - int legacy_windows_fs_encoding; -#endif - - /* Enable UTF-8 mode? (PEP 540) - - Disabled by default (equals to 0). - - Set to 1 by "-X utf8" and "-X utf8=1" command line options. - Set to 1 by PYTHONUTF8=1 environment variable. - - Set to 0 by "-X utf8=0" and PYTHONUTF8=0. - - If equals to -1, it is set to 1 if the LC_CTYPE locale is "C" or - "POSIX", otherwise it is set to 0. Inherit Py_UTF8Mode value value. */ - int utf8_mode; - - int dev_mode; /* Development mode. PYTHONDEVMODE, -X dev */ - - /* Memory allocator: PYTHONMALLOC env var. - See PyMemAllocatorName for valid values. */ - int allocator; -} _PyPreConfig; - -PyAPI_FUNC(void) _PyPreConfig_InitPythonConfig(_PyPreConfig *config); -PyAPI_FUNC(void) _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config); - - -/* --- _PyCoreConfig ---------------------------------------------- */ - -typedef struct { - int _config_version; /* Internal configuration version, - used for ABI compatibility */ - int _config_init; /* _PyConfigInitEnum value */ - - int isolated; /* Isolated mode? see _PyPreConfig.isolated */ - int use_environment; /* Use environment variables? see _PyPreConfig.use_environment */ - int dev_mode; /* Development mode? See _PyPreConfig.dev_mode */ - - /* Install signal handlers? Yes by default. */ - int install_signal_handlers; - - int use_hash_seed; /* PYTHONHASHSEED=x */ - unsigned long hash_seed; - - /* Enable faulthandler? - Set to 1 by -X faulthandler and PYTHONFAULTHANDLER. -1 means unset. */ - int faulthandler; - - /* Enable tracemalloc? - Set by -X tracemalloc=N and PYTHONTRACEMALLOC. -1 means unset */ - int tracemalloc; - - int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */ - int show_ref_count; /* -X showrefcount */ - int show_alloc_count; /* -X showalloccount */ - int dump_refs; /* PYTHONDUMPREFS */ - int malloc_stats; /* PYTHONMALLOCSTATS */ - - /* Python filesystem encoding and error handler: - sys.getfilesystemencoding() and sys.getfilesystemencodeerrors(). - - Default encoding and error handler: - - * if Py_SetStandardStreamEncoding() has been called: they have the - highest priority; - * PYTHONIOENCODING environment variable; - * The UTF-8 Mode uses UTF-8/surrogateescape; - * If Python forces the usage of the ASCII encoding (ex: C locale - or POSIX locale on FreeBSD or HP-UX), use ASCII/surrogateescape; - * locale encoding: ANSI code page on Windows, UTF-8 on Android and - VxWorks, LC_CTYPE locale encoding on other platforms; - * On Windows, "surrogateescape" error handler; - * "surrogateescape" error handler if the LC_CTYPE locale is "C" or "POSIX"; - * "surrogateescape" error handler if the LC_CTYPE locale has been coerced - (PEP 538); - * "strict" error handler. - - Supported error handlers: "strict", "surrogateescape" and - "surrogatepass". The surrogatepass error handler is only supported - if Py_DecodeLocale() and Py_EncodeLocale() use directly the UTF-8 codec; - it's only used on Windows. - - initfsencoding() updates the encoding to the Python codec name. - For example, "ANSI_X3.4-1968" is replaced with "ascii". - - On Windows, sys._enablelegacywindowsfsencoding() sets the - encoding/errors to mbcs/replace at runtime. - - - See Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors. - */ - wchar_t *filesystem_encoding; - wchar_t *filesystem_errors; - - wchar_t *pycache_prefix; /* PYTHONPYCACHEPREFIX, -X pycache_prefix=PATH */ - int parse_argv; /* Parse argv command line arguments? */ - - /* Command line arguments (sys.argv). - - Set parse_argv to 1 to parse argv as Python command line arguments - and then strip Python arguments from argv. - - If argv is empty, an empty string is added to ensure that sys.argv - always exists and is never empty. */ - _PyWstrList argv; - - /* Program name: - - - If Py_SetProgramName() was called, use its value. - - On macOS, use PYTHONEXECUTABLE environment variable if set. - - If WITH_NEXT_FRAMEWORK macro is defined, use __PYVENV_LAUNCHER__ - environment variable is set. - - Use argv[0] if available and non-empty. - - Use "python" on Windows, or "python3 on other platforms. */ - wchar_t *program_name; - - _PyWstrList xoptions; /* Command line -X options */ - _PyWstrList warnoptions; /* Warnings options */ - - /* If equal to zero, disable the import of the module site and the - site-dependent manipulations of sys.path that it entails. Also disable - these manipulations if site is explicitly imported later (call - site.main() if you want them to be triggered). - - Set to 0 by the -S command line option. If set to -1 (default), it is - set to !Py_NoSiteFlag. */ - int site_import; - - /* Bytes warnings: - - * If equal to 1, issue a warning when comparing bytes or bytearray with - str or bytes with int. - * If equal or greater to 2, issue an error. - - Incremented by the -b command line option. If set to -1 (default), inherit - Py_BytesWarningFlag value. */ - int bytes_warning; - - /* If greater than 0, enable inspect: when a script is passed as first - argument or the -c option is used, enter interactive mode after - executing the script or the command, even when sys.stdin does not appear - to be a terminal. - - Incremented by the -i command line option. Set to 1 if the PYTHONINSPECT - environment variable is non-empty. If set to -1 (default), inherit - Py_InspectFlag value. */ - int inspect; - - /* If greater than 0: enable the interactive mode (REPL). - - Incremented by the -i command line option. If set to -1 (default), - inherit Py_InteractiveFlag value. */ - int interactive; - - /* Optimization level. - - Incremented by the -O command line option. Set by the PYTHONOPTIMIZE - environment variable. If set to -1 (default), inherit Py_OptimizeFlag - value. */ - int optimization_level; - - /* If greater than 0, enable the debug mode: turn on parser debugging - output (for expert only, depending on compilation options). - - Incremented by the -d command line option. Set by the PYTHONDEBUG - environment variable. If set to -1 (default), inherit Py_DebugFlag - value. */ - int parser_debug; - - /* If equal to 0, Python won't try to write ``.pyc`` files on the - import of source modules. - - Set to 0 by the -B command line option and the PYTHONDONTWRITEBYTECODE - environment variable. If set to -1 (default), it is set to - !Py_DontWriteBytecodeFlag. */ - int write_bytecode; - - /* If greater than 0, enable the verbose mode: print a message each time a - module is initialized, showing the place (filename or built-in module) - from which it is loaded. - - If greater or equal to 2, print a message for each file that is checked - for when searching for a module. Also provides information on module - cleanup at exit. - - Incremented by the -v option. Set by the PYTHONVERBOSE environment - variable. If set to -1 (default), inherit Py_VerboseFlag value. */ - int verbose; - - /* If greater than 0, enable the quiet mode: Don't display the copyright - and version messages even in interactive mode. - - Incremented by the -q option. If set to -1 (default), inherit - Py_QuietFlag value. */ - int quiet; - - /* If greater than 0, don't add the user site-packages directory to - sys.path. - - Set to 0 by the -s and -I command line options , and the PYTHONNOUSERSITE - environment variable. If set to -1 (default), it is set to - !Py_NoUserSiteDirectory. */ - int user_site_directory; - - /* If non-zero, configure C standard steams (stdio, stdout, - stderr): - - - Set O_BINARY mode on Windows. - - If buffered_stdio is equal to zero, make streams unbuffered. - Otherwise, enable streams buffering if interactive is non-zero. */ - int configure_c_stdio; - - /* If equal to 0, enable unbuffered mode: force the stdout and stderr - streams to be unbuffered. - - Set to 0 by the -u option. Set by the PYTHONUNBUFFERED environment - variable. - If set to -1 (default), it is set to !Py_UnbufferedStdioFlag. */ - int buffered_stdio; - - /* Encoding of sys.stdin, sys.stdout and sys.stderr. - Value set from PYTHONIOENCODING environment variable and - Py_SetStandardStreamEncoding() function. - See also 'stdio_errors' attribute. */ - wchar_t *stdio_encoding; - - /* Error handler of sys.stdin and sys.stdout. - Value set from PYTHONIOENCODING environment variable and - Py_SetStandardStreamEncoding() function. - See also 'stdio_encoding' attribute. */ - wchar_t *stdio_errors; - -#ifdef MS_WINDOWS - /* If greater than zero, use io.FileIO instead of WindowsConsoleIO for sys - standard streams. - - Set to 1 if the PYTHONLEGACYWINDOWSSTDIO environment variable is set to - a non-empty string. If set to -1 (default), inherit - Py_LegacyWindowsStdioFlag value. - - See PEP 528 for more details. */ - int legacy_windows_stdio; -#endif - - /* --- Path configuration inputs ------------ */ - - wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ - wchar_t *home; /* PYTHONHOME environment variable, - see also Py_SetPythonHome(). */ - - /* --- Path configuration outputs ----------- */ - - int use_module_search_paths; /* If non-zero, use module_search_paths */ - _PyWstrList module_search_paths; /* sys.path paths. Computed if - use_module_search_paths is equal - to zero. */ - - wchar_t *executable; /* sys.executable */ - wchar_t *prefix; /* sys.prefix */ - wchar_t *base_prefix; /* sys.base_prefix */ - wchar_t *exec_prefix; /* sys.exec_prefix */ - wchar_t *base_exec_prefix; /* sys.base_exec_prefix */ - - /* --- Parameter only used by Py_Main() ---------- */ - - /* Skip the first line of the source ('run_filename' parameter), allowing use of non-Unix forms of - "#!cmd". This is intended for a DOS specific hack only. - - Set by the -x command line option. */ - int skip_source_first_line; - - wchar_t *run_command; /* -c command line argument */ - wchar_t *run_module; /* -m command line argument */ - wchar_t *run_filename; /* Trailing command line argument without -c or -m */ - - /* --- Private fields ---------------------------- */ - - /* Install importlib? If set to 0, importlib is not initialized at all. - Needed by freeze_importlib. */ - int _install_importlib; - - /* Value of the --check-hash-based-pycs command line option: - - - "default" means the 'check_source' flag in hash-based pycs - determines invalidation - - "always" causes the interpreter to hash the source file for - invalidation regardless of value of 'check_source' bit - - "never" causes the interpreter to always assume hash-based pycs are - valid - - The default value is "default". - - See PEP 552 "Deterministic pycs" for more details. */ - wchar_t *check_hash_pycs_mode; - - /* If greater than 0, suppress _PyPathConfig_Calculate() warnings on Unix. - The parameter has no effect on Windows. - - If set to -1 (default), inherit !Py_FrozenFlag value. */ - int pathconfig_warnings; - - /* If equal to 0, stop Python initialization before the "main" phase */ - int _init_main; - -} _PyCoreConfig; - -PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config); -PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString( - _PyCoreConfig *config, - wchar_t **config_str, - const wchar_t *str); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_DecodeLocale( - _PyCoreConfig *config, - wchar_t **config_str, - const char *str); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetArgv( - _PyCoreConfig *config, - Py_ssize_t argc, - char * const *argv); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideArgv(_PyCoreConfig *config, - Py_ssize_t argc, - wchar_t * const *argv); - -#ifdef __cplusplus -} -#endif -#endif /* !Py_LIMITED_API */ -#endif /* !Py_PYCORECONFIG_H */ diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h new file mode 100644 index 0000000..a98b91a --- /dev/null +++ b/Include/cpython/initconfig.h @@ -0,0 +1,429 @@ +#ifndef Py_PYCORECONFIG_H +#define Py_PYCORECONFIG_H +#ifndef Py_LIMITED_API +#ifdef __cplusplus +extern "C" { +#endif + +/* --- PyStatus ----------------------------------------------- */ + +typedef struct { + enum { + _PyStatus_TYPE_OK=0, + _PyStatus_TYPE_ERROR=1, + _PyStatus_TYPE_EXIT=2 + } _type; + const char *func; + const char *err_msg; + int exitcode; +} PyStatus; + +PyAPI_FUNC(PyStatus) PyStatus_Ok(void); +PyAPI_FUNC(PyStatus) PyStatus_Error(const char *err_msg); +PyAPI_FUNC(PyStatus) PyStatus_NoMemory(void); +PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode); +PyAPI_FUNC(int) PyStatus_IsError(PyStatus err); +PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err); +PyAPI_FUNC(int) PyStatus_Exception(PyStatus err); + +/* --- PyWideStringList ------------------------------------------------ */ + +typedef struct { + /* If length is greater than zero, items must be non-NULL + and all items strings must be non-NULL */ + Py_ssize_t length; + wchar_t **items; +} PyWideStringList; + +PyAPI_FUNC(PyStatus) PyWideStringList_Append(PyWideStringList *list, + const wchar_t *item); + + +/* --- PyPreConfig ----------------------------------------------- */ + +typedef struct { + int _config_version; /* Internal configuration version, + used for ABI compatibility */ + int _config_init; /* _PyConfigInitEnum value */ + + /* Parse Py_PreInitializeFromBytesArgs() arguments? + See PyConfig.parse_argv */ + int parse_argv; + + /* If greater than 0, enable isolated mode: sys.path contains + neither the script's directory nor the user's site-packages directory. + + Set to 1 by the -I command line option. If set to -1 (default), inherit + Py_IsolatedFlag value. */ + int isolated; + + /* If greater than 0: use environment variables. + Set to 0 by -E command line option. If set to -1 (default), it is + set to !Py_IgnoreEnvironmentFlag. */ + int use_environment; + + /* Set the LC_CTYPE locale to the user preferred locale? If equals to 0, + set coerce_c_locale and coerce_c_locale_warn to 0. */ + int configure_locale; + + /* Coerce the LC_CTYPE locale if it's equal to "C"? (PEP 538) + + Set to 0 by PYTHONCOERCECLOCALE=0. Set to 1 by PYTHONCOERCECLOCALE=1. + Set to 2 if the user preferred LC_CTYPE locale is "C". + + If it is equal to 1, LC_CTYPE locale is read to decide it it should be + coerced or not (ex: PYTHONCOERCECLOCALE=1). Internally, it is set to 2 + if the LC_CTYPE locale must be coerced. + + Disable by default (set to 0). Set it to -1 to let Python decides if it + should be enabled or not. */ + int coerce_c_locale; + + /* Emit a warning if the LC_CTYPE locale is coerced? + + Set to 1 by PYTHONCOERCECLOCALE=warn. + + Disable by default (set to 0). Set it to -1 to let Python decides if it + should be enabled or not. */ + int coerce_c_locale_warn; + +#ifdef MS_WINDOWS + /* If greater than 1, use the "mbcs" encoding instead of the UTF-8 + encoding for the filesystem encoding. + + Set to 1 if the PYTHONLEGACYWINDOWSFSENCODING environment variable is + set to a non-empty string. If set to -1 (default), inherit + Py_LegacyWindowsFSEncodingFlag value. + + See PEP 529 for more details. */ + int legacy_windows_fs_encoding; +#endif + + /* Enable UTF-8 mode? (PEP 540) + + Disabled by default (equals to 0). + + Set to 1 by "-X utf8" and "-X utf8=1" command line options. + Set to 1 by PYTHONUTF8=1 environment variable. + + Set to 0 by "-X utf8=0" and PYTHONUTF8=0. + + If equals to -1, it is set to 1 if the LC_CTYPE locale is "C" or + "POSIX", otherwise it is set to 0. Inherit Py_UTF8Mode value value. */ + int utf8_mode; + + int dev_mode; /* Development mode. PYTHONDEVMODE, -X dev */ + + /* Memory allocator: PYTHONMALLOC env var. + See PyMemAllocatorName for valid values. */ + int allocator; +} PyPreConfig; + +PyAPI_FUNC(void) PyPreConfig_InitPythonConfig(PyPreConfig *config); +PyAPI_FUNC(void) PyPreConfig_InitIsolatedConfig(PyPreConfig *config); + + +/* --- PyConfig ---------------------------------------------- */ + +typedef struct { + int _config_version; /* Internal configuration version, + used for ABI compatibility */ + int _config_init; /* _PyConfigInitEnum value */ + + int isolated; /* Isolated mode? see PyPreConfig.isolated */ + int use_environment; /* Use environment variables? see PyPreConfig.use_environment */ + int dev_mode; /* Development mode? See PyPreConfig.dev_mode */ + + /* Install signal handlers? Yes by default. */ + int install_signal_handlers; + + int use_hash_seed; /* PYTHONHASHSEED=x */ + unsigned long hash_seed; + + /* Enable faulthandler? + Set to 1 by -X faulthandler and PYTHONFAULTHANDLER. -1 means unset. */ + int faulthandler; + + /* Enable tracemalloc? + Set by -X tracemalloc=N and PYTHONTRACEMALLOC. -1 means unset */ + int tracemalloc; + + int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */ + int show_ref_count; /* -X showrefcount */ + int show_alloc_count; /* -X showalloccount */ + int dump_refs; /* PYTHONDUMPREFS */ + int malloc_stats; /* PYTHONMALLOCSTATS */ + + /* Python filesystem encoding and error handler: + sys.getfilesystemencoding() and sys.getfilesystemencodeerrors(). + + Default encoding and error handler: + + * if Py_SetStandardStreamEncoding() has been called: they have the + highest priority; + * PYTHONIOENCODING environment variable; + * The UTF-8 Mode uses UTF-8/surrogateescape; + * If Python forces the usage of the ASCII encoding (ex: C locale + or POSIX locale on FreeBSD or HP-UX), use ASCII/surrogateescape; + * locale encoding: ANSI code page on Windows, UTF-8 on Android and + VxWorks, LC_CTYPE locale encoding on other platforms; + * On Windows, "surrogateescape" error handler; + * "surrogateescape" error handler if the LC_CTYPE locale is "C" or "POSIX"; + * "surrogateescape" error handler if the LC_CTYPE locale has been coerced + (PEP 538); + * "strict" error handler. + + Supported error handlers: "strict", "surrogateescape" and + "surrogatepass". The surrogatepass error handler is only supported + if Py_DecodeLocale() and Py_EncodeLocale() use directly the UTF-8 codec; + it's only used on Windows. + + initfsencoding() updates the encoding to the Python codec name. + For example, "ANSI_X3.4-1968" is replaced with "ascii". + + On Windows, sys._enablelegacywindowsfsencoding() sets the + encoding/errors to mbcs/replace at runtime. + + + See Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors. + */ + wchar_t *filesystem_encoding; + wchar_t *filesystem_errors; + + wchar_t *pycache_prefix; /* PYTHONPYCACHEPREFIX, -X pycache_prefix=PATH */ + int parse_argv; /* Parse argv command line arguments? */ + + /* Command line arguments (sys.argv). + + Set parse_argv to 1 to parse argv as Python command line arguments + and then strip Python arguments from argv. + + If argv is empty, an empty string is added to ensure that sys.argv + always exists and is never empty. */ + PyWideStringList argv; + + /* Program name: + + - If Py_SetProgramName() was called, use its value. + - On macOS, use PYTHONEXECUTABLE environment variable if set. + - If WITH_NEXT_FRAMEWORK macro is defined, use __PYVENV_LAUNCHER__ + environment variable is set. + - Use argv[0] if available and non-empty. + - Use "python" on Windows, or "python3 on other platforms. */ + wchar_t *program_name; + + PyWideStringList xoptions; /* Command line -X options */ + PyWideStringList warnoptions; /* Warnings options */ + + /* If equal to zero, disable the import of the module site and the + site-dependent manipulations of sys.path that it entails. Also disable + these manipulations if site is explicitly imported later (call + site.main() if you want them to be triggered). + + Set to 0 by the -S command line option. If set to -1 (default), it is + set to !Py_NoSiteFlag. */ + int site_import; + + /* Bytes warnings: + + * If equal to 1, issue a warning when comparing bytes or bytearray with + str or bytes with int. + * If equal or greater to 2, issue an error. + + Incremented by the -b command line option. If set to -1 (default), inherit + Py_BytesWarningFlag value. */ + int bytes_warning; + + /* If greater than 0, enable inspect: when a script is passed as first + argument or the -c option is used, enter interactive mode after + executing the script or the command, even when sys.stdin does not appear + to be a terminal. + + Incremented by the -i command line option. Set to 1 if the PYTHONINSPECT + environment variable is non-empty. If set to -1 (default), inherit + Py_InspectFlag value. */ + int inspect; + + /* If greater than 0: enable the interactive mode (REPL). + + Incremented by the -i command line option. If set to -1 (default), + inherit Py_InteractiveFlag value. */ + int interactive; + + /* Optimization level. + + Incremented by the -O command line option. Set by the PYTHONOPTIMIZE + environment variable. If set to -1 (default), inherit Py_OptimizeFlag + value. */ + int optimization_level; + + /* If greater than 0, enable the debug mode: turn on parser debugging + output (for expert only, depending on compilation options). + + Incremented by the -d command line option. Set by the PYTHONDEBUG + environment variable. If set to -1 (default), inherit Py_DebugFlag + value. */ + int parser_debug; + + /* If equal to 0, Python won't try to write ``.pyc`` files on the + import of source modules. + + Set to 0 by the -B command line option and the PYTHONDONTWRITEBYTECODE + environment variable. If set to -1 (default), it is set to + !Py_DontWriteBytecodeFlag. */ + int write_bytecode; + + /* If greater than 0, enable the verbose mode: print a message each time a + module is initialized, showing the place (filename or built-in module) + from which it is loaded. + + If greater or equal to 2, print a message for each file that is checked + for when searching for a module. Also provides information on module + cleanup at exit. + + Incremented by the -v option. Set by the PYTHONVERBOSE environment + variable. If set to -1 (default), inherit Py_VerboseFlag value. */ + int verbose; + + /* If greater than 0, enable the quiet mode: Don't display the copyright + and version messages even in interactive mode. + + Incremented by the -q option. If set to -1 (default), inherit + Py_QuietFlag value. */ + int quiet; + + /* If greater than 0, don't add the user site-packages directory to + sys.path. + + Set to 0 by the -s and -I command line options , and the PYTHONNOUSERSITE + environment variable. If set to -1 (default), it is set to + !Py_NoUserSiteDirectory. */ + int user_site_directory; + + /* If non-zero, configure C standard steams (stdio, stdout, + stderr): + + - Set O_BINARY mode on Windows. + - If buffered_stdio is equal to zero, make streams unbuffered. + Otherwise, enable streams buffering if interactive is non-zero. */ + int configure_c_stdio; + + /* If equal to 0, enable unbuffered mode: force the stdout and stderr + streams to be unbuffered. + + Set to 0 by the -u option. Set by the PYTHONUNBUFFERED environment + variable. + If set to -1 (default), it is set to !Py_UnbufferedStdioFlag. */ + int buffered_stdio; + + /* Encoding of sys.stdin, sys.stdout and sys.stderr. + Value set from PYTHONIOENCODING environment variable and + Py_SetStandardStreamEncoding() function. + See also 'stdio_errors' attribute. */ + wchar_t *stdio_encoding; + + /* Error handler of sys.stdin and sys.stdout. + Value set from PYTHONIOENCODING environment variable and + Py_SetStandardStreamEncoding() function. + See also 'stdio_encoding' attribute. */ + wchar_t *stdio_errors; + +#ifdef MS_WINDOWS + /* If greater than zero, use io.FileIO instead of WindowsConsoleIO for sys + standard streams. + + Set to 1 if the PYTHONLEGACYWINDOWSSTDIO environment variable is set to + a non-empty string. If set to -1 (default), inherit + Py_LegacyWindowsStdioFlag value. + + See PEP 528 for more details. */ + int legacy_windows_stdio; +#endif + + /* Value of the --check-hash-based-pycs command line option: + + - "default" means the 'check_source' flag in hash-based pycs + determines invalidation + - "always" causes the interpreter to hash the source file for + invalidation regardless of value of 'check_source' bit + - "never" causes the interpreter to always assume hash-based pycs are + valid + + The default value is "default". + + See PEP 552 "Deterministic pycs" for more details. */ + wchar_t *check_hash_pycs_mode; + + /* --- Path configuration inputs ------------ */ + + /* If greater than 0, suppress _PyPathConfig_Calculate() warnings on Unix. + The parameter has no effect on Windows. + + If set to -1 (default), inherit !Py_FrozenFlag value. */ + int pathconfig_warnings; + + wchar_t *pythonpath_env; /* PYTHONPATH environment variable */ + wchar_t *home; /* PYTHONHOME environment variable, + see also Py_SetPythonHome(). */ + + /* --- Path configuration outputs ----------- */ + + int module_search_paths_set; /* If non-zero, use module_search_paths */ + PyWideStringList module_search_paths; /* sys.path paths. Computed if + module_search_paths_set is equal + to zero. */ + + wchar_t *executable; /* sys.executable */ + wchar_t *prefix; /* sys.prefix */ + wchar_t *base_prefix; /* sys.base_prefix */ + wchar_t *exec_prefix; /* sys.exec_prefix */ + wchar_t *base_exec_prefix; /* sys.base_exec_prefix */ + + /* --- Parameter only used by Py_Main() ---------- */ + + /* Skip the first line of the source ('run_filename' parameter), allowing use of non-Unix forms of + "#!cmd". This is intended for a DOS specific hack only. + + Set by the -x command line option. */ + int skip_source_first_line; + + wchar_t *run_command; /* -c command line argument */ + wchar_t *run_module; /* -m command line argument */ + wchar_t *run_filename; /* Trailing command line argument without -c or -m */ + + /* --- Private fields ---------------------------- */ + + /* Install importlib? If set to 0, importlib is not initialized at all. + Needed by freeze_importlib. */ + int _install_importlib; + + /* If equal to 0, stop Python initialization before the "main" phase */ + int _init_main; + +} PyConfig; + +PyAPI_FUNC(PyStatus) PyConfig_InitPythonConfig(PyConfig *config); +PyAPI_FUNC(PyStatus) PyConfig_InitIsolatedConfig(PyConfig *config); +PyAPI_FUNC(void) PyConfig_Clear(PyConfig *); +PyAPI_FUNC(PyStatus) PyConfig_SetString( + PyConfig *config, + wchar_t **config_str, + const wchar_t *str); +PyAPI_FUNC(PyStatus) PyConfig_SetBytesString( + PyConfig *config, + wchar_t **config_str, + const char *str); +PyAPI_FUNC(PyStatus) PyConfig_Read(PyConfig *config); +PyAPI_FUNC(PyStatus) PyConfig_SetBytesArgv( + PyConfig *config, + Py_ssize_t argc, + char * const *argv); +PyAPI_FUNC(PyStatus) PyConfig_SetArgv(PyConfig *config, + Py_ssize_t argc, + wchar_t * const *argv); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_LIMITED_API */ +#endif /* !Py_PYCORECONFIG_H */ diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index ba56664..2f3a0db 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -14,14 +14,14 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, /* PEP 432 Multi-phase initialization API (Private while provisional!) */ -PyAPI_FUNC(_PyInitError) _Py_PreInitialize( - const _PyPreConfig *src_config); -PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromArgs( - const _PyPreConfig *src_config, +PyAPI_FUNC(PyStatus) Py_PreInitialize( + const PyPreConfig *src_config); +PyAPI_FUNC(PyStatus) Py_PreInitializeFromBytesArgs( + const PyPreConfig *src_config, Py_ssize_t argc, char **argv); -PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromWideArgs( - const _PyPreConfig *src_config, +PyAPI_FUNC(PyStatus) Py_PreInitializeFromArgs( + const PyPreConfig *src_config, Py_ssize_t argc, wchar_t **argv); @@ -30,22 +30,22 @@ PyAPI_FUNC(int) _Py_IsCoreInitialized(void); /* Initialization and finalization */ -PyAPI_FUNC(_PyInitError) _Py_InitializeFromConfig( - const _PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _Py_InitializeFromArgs( - const _PyCoreConfig *config, +PyAPI_FUNC(PyStatus) Py_InitializeFromConfig( + const PyConfig *config); +PyAPI_FUNC(PyStatus) _Py_InitializeFromArgs( + const PyConfig *config, Py_ssize_t argc, char * const *argv); -PyAPI_FUNC(_PyInitError) _Py_InitializeFromWideArgs( - const _PyCoreConfig *config, +PyAPI_FUNC(PyStatus) _Py_InitializeFromWideArgs( + const PyConfig *config, Py_ssize_t argc, wchar_t * const *argv); -PyAPI_FUNC(_PyInitError) _Py_InitializeMain(void); +PyAPI_FUNC(PyStatus) _Py_InitializeMain(void); -PyAPI_FUNC(int) _Py_RunMain(void); +PyAPI_FUNC(int) Py_RunMain(void); -PyAPI_FUNC(void) _Py_NO_RETURN _Py_ExitInitError(_PyInitError err); +PyAPI_FUNC(void) _Py_NO_RETURN Py_ExitStatusException(PyStatus err); /* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level * exit functions. diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 94331f3..6b7663f 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -6,13 +6,11 @@ extern "C" { #endif -#include "cpython/coreconfig.h" +#include "cpython/initconfig.h" PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); -PyAPI_FUNC(_PyCoreConfig *) _PyInterpreterState_GetCoreConfig(PyInterpreterState *); - PyAPI_FUNC(PyObject *) _PyInterpreterState_GetMainModule(PyInterpreterState *); /* State unique per thread */ diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h deleted file mode 100644 index b17737a..0000000 --- a/Include/internal/pycore_coreconfig.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef Py_INTERNAL_CORECONFIG_H -#define Py_INTERNAL_CORECONFIG_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#include "pycore_pystate.h" /* _PyRuntimeState */ - -/* --- _PyInitError ----------------------------------------------- */ - -/* Almost all errors causing Python initialization to fail */ -#ifdef _MSC_VER - /* Visual Studio 2015 doesn't implement C99 __func__ in C */ -# define _Py_INIT_GET_FUNC() __FUNCTION__ -#else -# define _Py_INIT_GET_FUNC() __func__ -#endif - -#define _Py_INIT_OK() \ - (_PyInitError){._type = _Py_INIT_ERR_TYPE_OK,} - /* other fields are set to 0 */ -#define _Py_INIT_ERR(ERR_MSG) \ - (_PyInitError){ \ - ._type = _Py_INIT_ERR_TYPE_ERROR, \ - ._func = _Py_INIT_GET_FUNC(), \ - .err_msg = (ERR_MSG)} - /* other fields are set to 0 */ -#define _Py_INIT_NO_MEMORY() _Py_INIT_ERR("memory allocation failed") -#define _Py_INIT_EXIT(EXITCODE) \ - (_PyInitError){ \ - ._type = _Py_INIT_ERR_TYPE_EXIT, \ - .exitcode = (EXITCODE)} -#define _Py_INIT_IS_ERROR(err) \ - (err._type == _Py_INIT_ERR_TYPE_ERROR) -#define _Py_INIT_IS_EXIT(err) \ - (err._type == _Py_INIT_ERR_TYPE_EXIT) -#define _Py_INIT_FAILED(err) \ - (err._type != _Py_INIT_ERR_TYPE_OK) - -/* --- _PyWstrList ------------------------------------------------ */ - -#define _PyWstrList_INIT (_PyWstrList){.length = 0, .items = NULL} - -#ifndef NDEBUG -PyAPI_FUNC(int) _PyWstrList_CheckConsistency(const _PyWstrList *list); -#endif -PyAPI_FUNC(void) _PyWstrList_Clear(_PyWstrList *list); -PyAPI_FUNC(int) _PyWstrList_Copy(_PyWstrList *list, - const _PyWstrList *list2); -PyAPI_FUNC(int) _PyWstrList_Append(_PyWstrList *list, - const wchar_t *item); -PyAPI_FUNC(PyObject*) _PyWstrList_AsList(const _PyWstrList *list); -PyAPI_FUNC(int) _PyWstrList_Extend(_PyWstrList *list, - const _PyWstrList *list2); - - -/* --- _PyArgv ---------------------------------------------------- */ - -typedef struct { - Py_ssize_t argc; - int use_bytes_argv; - char * const *bytes_argv; - wchar_t * const *wchar_argv; -} _PyArgv; - -PyAPI_FUNC(_PyInitError) _PyArgv_AsWstrList(const _PyArgv *args, - _PyWstrList *list); - - -/* --- Helper functions ------------------------------------------- */ - -PyAPI_FUNC(int) _Py_str_to_int( - const char *str, - int *result); -PyAPI_FUNC(const wchar_t*) _Py_get_xoption( - const _PyWstrList *xoptions, - const wchar_t *name); -PyAPI_FUNC(const char*) _Py_GetEnv( - int use_environment, - const char *name); -PyAPI_FUNC(void) _Py_get_env_flag( - int use_environment, - int *flag, - const char *name); - -/* Py_GetArgcArgv() helper */ -PyAPI_FUNC(void) _Py_ClearArgcArgv(void); - - -/* --- _PyPreCmdline ------------------------------------------------- */ - -typedef struct { - _PyWstrList argv; - _PyWstrList xoptions; /* "-X value" option */ - int isolated; /* -I option */ - int use_environment; /* -E option */ - int dev_mode; /* -X dev and PYTHONDEVMODE */ -} _PyPreCmdline; - -#define _PyPreCmdline_INIT \ - (_PyPreCmdline){ \ - .use_environment = -1, \ - .isolated = -1, \ - .dev_mode = -1} -/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */ - -PyAPI_FUNC(void) _PyPreCmdline_Clear(_PyPreCmdline *cmdline); -PyAPI_FUNC(_PyInitError) _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, - const _PyArgv *args); -PyAPI_FUNC(int) _PyPreCmdline_SetCoreConfig( - const _PyPreCmdline *cmdline, - _PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline, - const _PyPreConfig *preconfig); - - -/* --- _PyPreConfig ----------------------------------------------- */ - -PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(_PyPreConfig *config); -PyAPI_FUNC(void) _PyPreConfig_InitFromCoreConfig( - _PyPreConfig *config, - const _PyCoreConfig *coreconfig); -PyAPI_FUNC(void) _PyPreConfig_InitFromPreConfig( - _PyPreConfig *config, - const _PyPreConfig *config2); -PyAPI_FUNC(void) _PyPreConfig_Copy(_PyPreConfig *config, - const _PyPreConfig *config2); -PyAPI_FUNC(PyObject*) _PyPreConfig_AsDict(const _PyPreConfig *config); -PyAPI_FUNC(void) _PyPreConfig_GetCoreConfig(_PyPreConfig *config, - const _PyCoreConfig *core_config); -PyAPI_FUNC(_PyInitError) _PyPreConfig_Read(_PyPreConfig *config, - const _PyArgv *args); -PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(const _PyPreConfig *config); - - -/* --- _PyCoreConfig ---------------------------------------------- */ - -PyAPI_FUNC(void) _PyCoreConfig_InitCompatConfig(_PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy( - _PyCoreConfig *config, - const _PyCoreConfig *config2); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig( - const _PyCoreConfig *config); -PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config, - _PyRuntimeState *runtime); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPyArgv( - _PyCoreConfig *config, - const _PyArgv *args); - - -/* --- Function used for testing ---------------------------------- */ - -PyAPI_FUNC(PyObject*) _Py_GetConfigsAsDict(void); - -#ifdef __cplusplus -} -#endif -#endif /* !Py_INTERNAL_CORECONFIG_H */ diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h new file mode 100644 index 0000000..c0b3d95 --- /dev/null +++ b/Include/internal/pycore_initconfig.h @@ -0,0 +1,168 @@ +#ifndef Py_INTERNAL_CORECONFIG_H +#define Py_INTERNAL_CORECONFIG_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_pystate.h" /* _PyRuntimeState */ + +/* --- PyStatus ----------------------------------------------- */ + +/* Almost all errors causing Python initialization to fail */ +#ifdef _MSC_VER + /* Visual Studio 2015 doesn't implement C99 __func__ in C */ +# define _PyStatus_GET_FUNC() __FUNCTION__ +#else +# define _PyStatus_GET_FUNC() __func__ +#endif + +#define _PyStatus_OK() \ + (PyStatus){._type = _PyStatus_TYPE_OK,} + /* other fields are set to 0 */ +#define _PyStatus_ERR(ERR_MSG) \ + (PyStatus){ \ + ._type = _PyStatus_TYPE_ERROR, \ + .func = _PyStatus_GET_FUNC(), \ + .err_msg = (ERR_MSG)} + /* other fields are set to 0 */ +#define _PyStatus_NO_MEMORY() _PyStatus_ERR("memory allocation failed") +#define _PyStatus_EXIT(EXITCODE) \ + (PyStatus){ \ + ._type = _PyStatus_TYPE_EXIT, \ + .exitcode = (EXITCODE)} +#define _PyStatus_IS_ERROR(err) \ + (err._type == _PyStatus_TYPE_ERROR) +#define _PyStatus_IS_EXIT(err) \ + (err._type == _PyStatus_TYPE_EXIT) +#define _PyStatus_EXCEPTION(err) \ + (err._type != _PyStatus_TYPE_OK) + +/* --- PyWideStringList ------------------------------------------------ */ + +#define PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL} + +#ifndef NDEBUG +PyAPI_FUNC(int) _PyWideStringList_CheckConsistency(const PyWideStringList *list); +#endif +PyAPI_FUNC(void) _PyWideStringList_Clear(PyWideStringList *list); +PyAPI_FUNC(int) _PyWideStringList_Copy(PyWideStringList *list, + const PyWideStringList *list2); +PyAPI_FUNC(PyStatus) _PyWideStringList_Extend(PyWideStringList *list, + const PyWideStringList *list2); +PyAPI_FUNC(PyObject*) _PyWideStringList_AsList(const PyWideStringList *list); + + +/* --- _PyArgv ---------------------------------------------------- */ + +typedef struct { + Py_ssize_t argc; + int use_bytes_argv; + char * const *bytes_argv; + wchar_t * const *wchar_argv; +} _PyArgv; + +PyAPI_FUNC(PyStatus) _PyArgv_AsWstrList(const _PyArgv *args, + PyWideStringList *list); + + +/* --- Helper functions ------------------------------------------- */ + +PyAPI_FUNC(int) _Py_str_to_int( + const char *str, + int *result); +PyAPI_FUNC(const wchar_t*) _Py_get_xoption( + const PyWideStringList *xoptions, + const wchar_t *name); +PyAPI_FUNC(const char*) _Py_GetEnv( + int use_environment, + const char *name); +PyAPI_FUNC(void) _Py_get_env_flag( + int use_environment, + int *flag, + const char *name); + +/* Py_GetArgcArgv() helper */ +PyAPI_FUNC(void) _Py_ClearArgcArgv(void); + + +/* --- _PyPreCmdline ------------------------------------------------- */ + +typedef struct { + PyWideStringList argv; + PyWideStringList xoptions; /* "-X value" option */ + int isolated; /* -I option */ + int use_environment; /* -E option */ + int dev_mode; /* -X dev and PYTHONDEVMODE */ +} _PyPreCmdline; + +#define _PyPreCmdline_INIT \ + (_PyPreCmdline){ \ + .use_environment = -1, \ + .isolated = -1, \ + .dev_mode = -1} +/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */ + +extern void _PyPreCmdline_Clear(_PyPreCmdline *cmdline); +extern PyStatus _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, + const _PyArgv *args); +extern PyStatus _PyPreCmdline_SetConfig( + const _PyPreCmdline *cmdline, + PyConfig *config); +extern PyStatus _PyPreCmdline_Read(_PyPreCmdline *cmdline, + const PyPreConfig *preconfig); + + +/* --- PyPreConfig ----------------------------------------------- */ + +PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig); +extern void _PyPreConfig_InitFromConfig( + PyPreConfig *preconfig, + const PyConfig *config); +extern void _PyPreConfig_InitFromPreConfig( + PyPreConfig *preconfig, + const PyPreConfig *config2); +extern PyObject* _PyPreConfig_AsDict(const PyPreConfig *preconfig); +extern void _PyPreConfig_GetConfig(PyPreConfig *preconfig, + const PyConfig *config); +extern PyStatus _PyPreConfig_Read(PyPreConfig *preconfig, + const _PyArgv *args); +extern PyStatus _PyPreConfig_Write(const PyPreConfig *preconfig); + + +/* --- PyConfig ---------------------------------------------- */ + +#define _Py_CONFIG_VERSION 1 + +typedef enum { + /* Py_Initialize() API: backward compatibility with Python 3.6 and 3.7 */ + _PyConfig_INIT_COMPAT = 1, + _PyConfig_INIT_PYTHON = 2, + _PyConfig_INIT_ISOLATED = 3 +} _PyConfigInitEnum; + +PyAPI_FUNC(void) _PyConfig_InitCompatConfig(PyConfig *config); +extern PyStatus _PyConfig_Copy( + PyConfig *config, + const PyConfig *config2); +extern PyStatus _PyConfig_InitPathConfig(PyConfig *config); +extern PyStatus _PyConfig_SetPathConfig( + const PyConfig *config); +extern void _PyConfig_Write(const PyConfig *config, + _PyRuntimeState *runtime); +extern PyStatus _PyConfig_SetPyArgv( + PyConfig *config, + const _PyArgv *args); + + +/* --- Function used for testing ---------------------------------- */ + +PyAPI_FUNC(PyObject*) _Py_GetConfigsAsDict(void); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_CORECONFIG_H */ diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index bee3911..be12c6f 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -37,17 +37,17 @@ typedef struct _PyPathConfig { PyAPI_DATA(_PyPathConfig) _Py_path_config; -PyAPI_FUNC(void) _PyPathConfig_ClearGlobal(void); -PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal( - const struct _PyPathConfig *config); - -PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl( - _PyPathConfig *config, - const _PyCoreConfig *core_config); -PyAPI_FUNC(int) _PyPathConfig_ComputeSysPath0( - const _PyWstrList *argv, +extern void _PyPathConfig_ClearGlobal(void); +extern PyStatus _PyPathConfig_SetGlobal( + const struct _PyPathConfig *pathconfig); + +extern PyStatus _PyPathConfig_Calculate( + _PyPathConfig *pathconfig, + const PyConfig *config); +extern int _PyPathConfig_ComputeSysPath0( + const PyWideStringList *argv, PyObject **path0); -PyAPI_FUNC(int) _Py_FindEnvConfigValue( +extern int _Py_FindEnvConfigValue( FILE *env_file, const wchar_t *key, wchar_t *value, diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 13a31c2..69761ce 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -8,20 +8,20 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_coreconfig.h" /* _PyArgv */ +#include "pycore_initconfig.h" /* _PyArgv */ #include "pycore_pystate.h" /* _PyRuntimeState */ /* True if the main interpreter thread exited due to an unhandled * KeyboardInterrupt exception, suggesting the user pressed ^C. */ PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; -PyAPI_FUNC(int) _Py_UnixMain(int argc, char **argv); +PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); extern int _Py_SetFileSystemEncoding( const char *encoding, const char *errors); extern void _Py_ClearFileSystemEncoding(void); -extern _PyInitError _PyUnicode_InitEncodings(PyInterpreterState *interp); +extern PyStatus _PyUnicode_InitEncodings(PyInterpreterState *interp); #ifdef MS_WINDOWS extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void); #endif @@ -32,30 +32,30 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc); /* Various one-time initializers */ -extern _PyInitError _PyUnicode_Init(void); +extern PyStatus _PyUnicode_Init(void); extern int _PyStructSequence_Init(void); extern int _PyLong_Init(void); -extern _PyInitError _PyFaulthandler_Init(int enable); +extern PyStatus _PyFaulthandler_Init(int enable); extern int _PyTraceMalloc_Init(int enable); extern PyObject * _PyBuiltin_Init(void); -extern _PyInitError _PySys_Create( +extern PyStatus _PySys_Create( _PyRuntimeState *runtime, PyInterpreterState *interp, PyObject **sysmod_p); -extern _PyInitError _PySys_SetPreliminaryStderr(PyObject *sysdict); +extern PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict); extern int _PySys_InitMain( _PyRuntimeState *runtime, PyInterpreterState *interp); -extern _PyInitError _PyImport_Init(PyInterpreterState *interp); -extern _PyInitError _PyExc_Init(void); -extern _PyInitError _PyErr_Init(void); -extern _PyInitError _PyBuiltins_AddExceptions(PyObject * bltinmod); -extern _PyInitError _PyImportHooks_Init(void); +extern PyStatus _PyImport_Init(PyInterpreterState *interp); +extern PyStatus _PyExc_Init(void); +extern PyStatus _PyErr_Init(void); +extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod); +extern PyStatus _PyImportHooks_Init(void); extern int _PyFloat_Init(void); -extern _PyInitError _Py_HashRandomization_Init(const _PyCoreConfig *); +extern PyStatus _Py_HashRandomization_Init(const PyConfig *); -extern _PyInitError _PyTypes_Init(void); -extern _PyInitError _PyImportZip_Init(PyInterpreterState *interp); +extern PyStatus _PyTypes_Init(void); +extern PyStatus _PyImportZip_Init(PyInterpreterState *interp); /* Various internal finalizers */ @@ -94,11 +94,11 @@ extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(_PyRuntimeState *runtime); -PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPyArgv( - const _PyPreConfig *src_config, +PyAPI_FUNC(PyStatus) _Py_PreInitializeFromPyArgv( + const PyPreConfig *src_config, const _PyArgv *args); -PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromCoreConfig( - const _PyCoreConfig *coreconfig, +PyAPI_FUNC(PyStatus) _Py_PreInitializeFromConfig( + const PyConfig *config, const _PyArgv *args); diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index ef1d8a0..3ab4009 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -8,7 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "cpython/coreconfig.h" +#include "cpython/initconfig.h" #include "fileobject.h" #include "pystate.h" #include "pythread.h" @@ -106,7 +106,7 @@ struct _is { _Py_error_handler error_handler; } fs_codec; - _PyCoreConfig core_config; + PyConfig config; #ifdef HAVE_DLOPEN int dlopenflags; #endif @@ -193,7 +193,7 @@ struct _gilstate_runtime_state { /* Full Python runtime state */ typedef struct pyruntimestate { - /* Is Python pre-initialized? Set to 1 by _Py_PreInitialize() */ + /* Is Python pre-initialized? Set to 1 by Py_PreInitialize() */ int pre_initialized; /* Is Python core initialized? Set to 1 by _Py_InitializeCore() */ @@ -234,7 +234,7 @@ typedef struct pyruntimestate { struct _ceval_runtime_state ceval; struct _gilstate_runtime_state gilstate; - _PyPreConfig preconfig; + PyPreConfig preconfig; Py_OpenCodeHookFunction open_code_hook; void *open_code_userdata; @@ -248,13 +248,13 @@ typedef struct pyruntimestate { /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ PyAPI_DATA(_PyRuntimeState) _PyRuntime; -PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *runtime); +PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime); /* Initialize _PyRuntimeState. Return NULL on success, or return an error message on failure. */ -PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void); +PyAPI_FUNC(PyStatus) _PyRuntime_Initialize(void); PyAPI_FUNC(void) _PyRuntime_Finalize(void); @@ -307,7 +307,7 @@ PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap( struct _gilstate_runtime_state *gilstate, PyThreadState *newts); -PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *runtime); +PyAPI_FUNC(PyStatus) _PyInterpreterState_Enable(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime); diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 87e90f7..a39ef2b 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -272,7 +272,7 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase): def test_run_main(self): out, err = self.run_embedded_interpreter("test_run_main") - self.assertEqual(out.rstrip(), "_Py_RunMain(): sys.argv=['-c', 'arg2']") + self.assertEqual(out.rstrip(), "Py_RunMain(): sys.argv=['-c', 'arg2']") self.assertEqual(err, '') @@ -321,7 +321,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'use_environment', ] - CORE_CONFIG_COMPAT = { + CONFIG_COMPAT = { '_config_init': API_COMPAT, 'isolated': 0, 'use_environment': 1, @@ -349,7 +349,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'xoptions': [], 'warnoptions': [], - 'module_search_path_env': None, + 'pythonpath_env': None, 'home': None, 'executable': GET_DEFAULT_CONFIG, @@ -386,16 +386,16 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): '_init_main': 1, } if MS_WINDOWS: - CORE_CONFIG_COMPAT.update({ + CONFIG_COMPAT.update({ 'legacy_windows_stdio': 0, }) - CORE_CONFIG_PYTHON = dict(CORE_CONFIG_COMPAT, + CONFIG_PYTHON = dict(CONFIG_COMPAT, _config_init=API_PYTHON, configure_c_stdio=1, parse_argv=1, ) - CORE_CONFIG_ISOLATED = dict(CORE_CONFIG_COMPAT, + CONFIG_ISOLATED = dict(CONFIG_COMPAT, _config_init=API_ISOLATED, isolated=1, use_environment=0, @@ -408,7 +408,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): pathconfig_warnings=0, ) if MS_WINDOWS: - CORE_CONFIG_ISOLATED['legacy_windows_stdio'] = 0 + CONFIG_ISOLATED['legacy_windows_stdio'] = 0 # global config DEFAULT_GLOBAL_CONFIG = { @@ -535,12 +535,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): if expected['program_name'] is self.GET_DEFAULT_CONFIG: expected['program_name'] = './_testembed' - core_config = configs['core_config'] + config = configs['config'] for key, value in expected.items(): if value is self.GET_DEFAULT_CONFIG: - expected[key] = core_config[key] + expected[key] = config[key] - prepend_path = expected['module_search_path_env'] + prepend_path = expected['pythonpath_env'] if prepend_path is not None: expected['module_search_paths'] = [prepend_path, *expected['module_search_paths']] if add_path is not None: @@ -550,34 +550,34 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): if key not in expected_preconfig: expected_preconfig[key] = expected[key] - def check_pre_config(self, config, expected): - pre_config = dict(config['pre_config']) + def check_pre_config(self, configs, expected): + pre_config = dict(configs['pre_config']) for key, value in list(expected.items()): if value is self.IGNORE_CONFIG: del pre_config[key] del expected[key] self.assertEqual(pre_config, expected) - def check_core_config(self, config, expected): - core_config = dict(config['core_config']) + def check_config(self, configs, expected): + config = dict(configs['config']) for key, value in list(expected.items()): if value is self.IGNORE_CONFIG: - del core_config[key] + del config[key] del expected[key] - self.assertEqual(core_config, expected) + self.assertEqual(config, expected) - def check_global_config(self, config): - pre_config = config['pre_config'] - core_config = config['core_config'] + def check_global_config(self, configs): + pre_config = configs['pre_config'] + config = configs['config'] expected = dict(self.DEFAULT_GLOBAL_CONFIG) for item in self.COPY_GLOBAL_CONFIG: if len(item) == 3: global_key, core_key, opposite = item - expected[global_key] = 0 if core_config[core_key] else 1 + expected[global_key] = 0 if config[core_key] else 1 else: global_key, core_key = item - expected[global_key] = core_config[core_key] + expected[global_key] = config[core_key] for item in self.COPY_GLOBAL_PRE_CONFIG: if len(item) == 3: global_key, core_key, opposite = item @@ -586,9 +586,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): global_key, core_key = item expected[global_key] = pre_config[core_key] - self.assertEqual(config['global_config'], expected) + self.assertEqual(configs['global_config'], expected) - def check_config(self, testname, expected_config=None, + def check_all_configs(self, testname, expected_config=None, expected_preconfig=None, add_path=None, stderr=None, *, api): env = dict(os.environ) @@ -610,11 +610,11 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): expected_config = {} if api == API_PYTHON: - default_config = self.CORE_CONFIG_PYTHON + default_config = self.CONFIG_PYTHON elif api == API_ISOLATED: - default_config = self.CORE_CONFIG_ISOLATED + default_config = self.CONFIG_ISOLATED else: - default_config = self.CORE_CONFIG_COMPAT + default_config = self.CONFIG_COMPAT expected_config = dict(default_config, **expected_config) self.get_expected_config(expected_preconfig, @@ -627,22 +627,22 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): if stderr is not None: self.assertEqual(err.rstrip(), stderr) try: - config = json.loads(out) + configs = json.loads(out) except json.JSONDecodeError: self.fail(f"fail to decode stdout: {out!r}") - self.check_pre_config(config, expected_preconfig) - self.check_core_config(config, expected_config) - self.check_global_config(config) + self.check_pre_config(configs, expected_preconfig) + self.check_config(configs, expected_config) + self.check_global_config(configs) def test_init_default_config(self): - self.check_config("test_init_initialize_config", api=API_COMPAT) + self.check_all_configs("test_init_initialize_config", api=API_COMPAT) def test_preinit_compat_config(self): - self.check_config("test_preinit_compat_config", api=API_COMPAT) + self.check_all_configs("test_preinit_compat_config", api=API_COMPAT) def test_init_compat_config(self): - self.check_config("test_init_compat_config", api=API_COMPAT) + self.check_all_configs("test_init_compat_config", api=API_COMPAT) def test_init_global_config(self): preconfig = { @@ -664,8 +664,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'user_site_directory': 0, 'pathconfig_warnings': 0, } - self.check_config("test_init_global_config", config, preconfig, - api=API_COMPAT) + self.check_all_configs("test_init_global_config", config, preconfig, + api=API_COMPAT) def test_init_from_config(self): preconfig = { @@ -689,7 +689,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'program_name': './conf_program_name', 'argv': ['-c', 'arg2'], 'parse_argv': 1, - 'xoptions': ['core_xoption1=3', 'core_xoption2=', 'core_xoption3'], + 'xoptions': ['xoption1=3', 'xoption2=', 'xoption3'], 'warnoptions': ['error::ResourceWarning', 'default::BytesWarning'], 'run_command': 'pass\n', @@ -709,8 +709,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'check_hash_pycs_mode': 'always', 'pathconfig_warnings': 0, } - self.check_config("test_init_from_config", config, preconfig, - api=API_COMPAT) + self.check_all_configs("test_init_from_config", config, preconfig, + api=API_COMPAT) def test_init_compat_env(self): preconfig = { @@ -724,7 +724,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'malloc_stats': 1, 'inspect': 1, 'optimization_level': 2, - 'module_search_path_env': '/my/path', + 'pythonpath_env': '/my/path', 'pycache_prefix': 'env_pycache_prefix', 'write_bytecode': 0, 'verbose': 1, @@ -735,8 +735,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'faulthandler': 1, 'warnoptions': ['EnvVar'], } - self.check_config("test_init_compat_env", config, preconfig, - api=API_COMPAT) + self.check_all_configs("test_init_compat_env", config, preconfig, + api=API_COMPAT) def test_init_python_env(self): preconfig = { @@ -751,7 +751,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'malloc_stats': 1, 'inspect': 1, 'optimization_level': 2, - 'module_search_path_env': '/my/path', + 'pythonpath_env': '/my/path', 'pycache_prefix': 'env_pycache_prefix', 'write_bytecode': 0, 'verbose': 1, @@ -762,24 +762,24 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'faulthandler': 1, 'warnoptions': ['EnvVar'], } - self.check_config("test_init_python_env", config, preconfig, - api=API_PYTHON) + self.check_all_configs("test_init_python_env", config, preconfig, + api=API_PYTHON) def test_init_env_dev_mode(self): preconfig = dict(allocator=PYMEM_ALLOCATOR_DEBUG) config = dict(dev_mode=1, faulthandler=1, warnoptions=['default']) - self.check_config("test_init_env_dev_mode", config, preconfig, - api=API_COMPAT) + self.check_all_configs("test_init_env_dev_mode", config, preconfig, + api=API_COMPAT) def test_init_env_dev_mode_alloc(self): preconfig = dict(allocator=PYMEM_ALLOCATOR_MALLOC) config = dict(dev_mode=1, faulthandler=1, warnoptions=['default']) - self.check_config("test_init_env_dev_mode_alloc", config, preconfig, - api=API_COMPAT) + self.check_all_configs("test_init_env_dev_mode_alloc", config, preconfig, + api=API_COMPAT) def test_init_dev_mode(self): preconfig = { @@ -790,8 +790,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'dev_mode': 1, 'warnoptions': ['default'], } - self.check_config("test_init_dev_mode", config, preconfig, - api=API_PYTHON) + self.check_all_configs("test_init_dev_mode", config, preconfig, + api=API_PYTHON) def test_preinit_parse_argv(self): # Pre-initialize implicitly using argv: make sure that -X dev @@ -807,8 +807,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'warnoptions': ['default'], 'xoptions': ['dev'], } - self.check_config("test_preinit_parse_argv", config, preconfig, - api=API_PYTHON) + self.check_all_configs("test_preinit_parse_argv", config, preconfig, + api=API_PYTHON) def test_preinit_dont_parse_argv(self): # -X dev must be ignored by isolated preconfiguration @@ -820,8 +820,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): "-X", "dev", "-X", "utf8", "script.py"], 'isolated': 0, } - self.check_config("test_preinit_dont_parse_argv", config, preconfig, - api=API_ISOLATED) + self.check_all_configs("test_preinit_dont_parse_argv", config, preconfig, + api=API_ISOLATED) def test_init_isolated_flag(self): config = { @@ -829,7 +829,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'use_environment': 0, 'user_site_directory': 0, } - self.check_config("test_init_isolated_flag", config, api=API_PYTHON) + self.check_all_configs("test_init_isolated_flag", config, api=API_PYTHON) def test_preinit_isolated1(self): # _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set @@ -838,7 +838,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'use_environment': 0, 'user_site_directory': 0, } - self.check_config("test_preinit_isolated1", config, api=API_COMPAT) + self.check_all_configs("test_preinit_isolated1", config, api=API_COMPAT) def test_preinit_isolated2(self): # _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 @@ -847,19 +847,19 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'use_environment': 0, 'user_site_directory': 0, } - self.check_config("test_preinit_isolated2", config, api=API_COMPAT) + self.check_all_configs("test_preinit_isolated2", config, api=API_COMPAT) def test_preinit_isolated_config(self): - self.check_config("test_preinit_isolated_config", api=API_ISOLATED) + self.check_all_configs("test_preinit_isolated_config", api=API_ISOLATED) def test_init_isolated_config(self): - self.check_config("test_init_isolated_config", api=API_ISOLATED) + self.check_all_configs("test_init_isolated_config", api=API_ISOLATED) def test_preinit_python_config(self): - self.check_config("test_preinit_python_config", api=API_PYTHON) + self.check_all_configs("test_preinit_python_config", api=API_PYTHON) def test_init_python_config(self): - self.check_config("test_init_python_config", api=API_PYTHON) + self.check_all_configs("test_init_python_config", api=API_PYTHON) def test_init_dont_configure_locale(self): # _PyPreConfig.configure_locale=0 @@ -867,64 +867,64 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'configure_locale': 0, 'coerce_c_locale': 0, } - self.check_config("test_init_dont_configure_locale", {}, preconfig, - api=API_PYTHON) + self.check_all_configs("test_init_dont_configure_locale", {}, preconfig, + api=API_PYTHON) def test_init_read_set(self): - core_config = { + config = { 'program_name': './init_read_set', 'executable': 'my_executable', } - self.check_config("test_init_read_set", core_config, - api=API_PYTHON, - add_path="init_read_set_path") + self.check_all_configs("test_init_read_set", config, + api=API_PYTHON, + add_path="init_read_set_path") def test_init_run_main(self): code = ('import _testinternalcapi, json; ' 'print(json.dumps(_testinternalcapi.get_configs()))') - core_config = { + config = { 'argv': ['-c', 'arg2'], 'program_name': './python3', 'run_command': code + '\n', 'parse_argv': 1, } - self.check_config("test_init_run_main", core_config, api=API_PYTHON) + self.check_all_configs("test_init_run_main", config, api=API_PYTHON) def test_init_main(self): code = ('import _testinternalcapi, json; ' 'print(json.dumps(_testinternalcapi.get_configs()))') - core_config = { + config = { 'argv': ['-c', 'arg2'], 'program_name': './python3', 'run_command': code + '\n', 'parse_argv': 1, '_init_main': 0, } - self.check_config("test_init_main", core_config, - api=API_PYTHON, - stderr="Run Python code before _Py_InitializeMain") + self.check_all_configs("test_init_main", config, + api=API_PYTHON, + stderr="Run Python code before _Py_InitializeMain") def test_init_parse_argv(self): - core_config = { + config = { 'parse_argv': 1, 'argv': ['-c', 'arg1', '-v', 'arg3'], 'program_name': './argv0', 'run_command': 'pass\n', 'use_environment': 0, } - self.check_config("test_init_parse_argv", core_config, api=API_PYTHON) + self.check_all_configs("test_init_parse_argv", config, api=API_PYTHON) def test_init_dont_parse_argv(self): pre_config = { 'parse_argv': 0, } - core_config = { + config = { 'parse_argv': 0, 'argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'], 'program_name': './argv0', } - self.check_config("test_init_dont_parse_argv", core_config, pre_config, - api=API_PYTHON) + self.check_all_configs("test_init_dont_parse_argv", config, pre_config, + api=API_PYTHON) class AuditingTests(EmbeddingTestsMixin, unittest.TestCase): diff --git a/Makefile.pre.in b/Makefile.pre.in index 8071a94..0bf5df4 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -322,7 +322,7 @@ PYTHON_OBJS= \ Python/ceval.o \ Python/codecs.o \ Python/compile.o \ - Python/coreconfig.o \ + Python/context.o \ Python/dynamic_annotations.o \ Python/errors.o \ Python/frozenmain.o \ @@ -333,8 +333,10 @@ PYTHON_OBJS= \ Python/getplatform.o \ Python/getversion.o \ Python/graminit.o \ + Python/hamt.o \ Python/import.o \ Python/importdl.o \ + Python/initconfig.o \ Python/marshal.o \ Python/modsupport.o \ Python/mysnprintf.o \ @@ -349,8 +351,6 @@ PYTHON_OBJS= \ Python/pylifecycle.o \ Python/pymath.o \ Python/pystate.o \ - Python/context.o \ - Python/hamt.o \ Python/pythonrun.o \ Python/pytime.o \ Python/bootstrap_hash.o \ @@ -1052,9 +1052,9 @@ PYTHON_HEADERS= \ $(srcdir)/Include/Python-ast.h \ \ $(srcdir)/Include/cpython/abstract.h \ - $(srcdir)/Include/cpython/coreconfig.h \ $(srcdir)/Include/cpython/dictobject.h \ $(srcdir)/Include/cpython/fileobject.h \ + $(srcdir)/Include/cpython/initconfig.h \ $(srcdir)/Include/cpython/interpreteridobject.h \ $(srcdir)/Include/cpython/object.h \ $(srcdir)/Include/cpython/objimpl.h \ @@ -1072,11 +1072,11 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_ceval.h \ $(srcdir)/Include/internal/pycore_condvar.h \ $(srcdir)/Include/internal/pycore_context.h \ - $(srcdir)/Include/internal/pycore_coreconfig.h \ $(srcdir)/Include/internal/pycore_fileutils.h \ $(srcdir)/Include/internal/pycore_getopt.h \ $(srcdir)/Include/internal/pycore_gil.h \ $(srcdir)/Include/internal/pycore_hamt.h \ + $(srcdir)/Include/internal/pycore_initconfig.h \ $(srcdir)/Include/internal/pycore_object.h \ $(srcdir)/Include/internal/pycore_pathconfig.h \ $(srcdir)/Include/internal/pycore_pyerrors.h \ diff --git a/Misc/NEWS.d/next/C API/2019-05-27-12-25-25.bpo-36763.bHCA9j.rst b/Misc/NEWS.d/next/C API/2019-05-27-12-25-25.bpo-36763.bHCA9j.rst new file mode 100644 index 0000000..fc5a481 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-05-27-12-25-25.bpo-36763.bHCA9j.rst @@ -0,0 +1 @@ +Implement the :pep:`587` "Python Initialization Configuration". diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index ba8f001..5c2f019 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -377,7 +377,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, { PyObject *RawIO_class = (PyObject *)&PyFileIO_Type; #ifdef MS_WINDOWS - _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (!config->legacy_windows_stdio && _PyIO_get_console_type(path_or_fd) != '\0') { RawIO_class = (PyObject *)&PyWindowsConsoleIO_Type; encoding = "utf-8"; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 6a0d9be..a5727b8 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -288,7 +288,7 @@ iobase_finalize(PyObject *self) shutdown issues). */ if (res == NULL) { #ifndef Py_DEBUG - const _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + const PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (config->dev_mode) { PyErr_WriteUnraisable(self); } diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 3a43ec1..3ea77e6 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -9,7 +9,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" static PyObject * diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index aa466c4..f2b5a50 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1,5 +1,5 @@ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_traceback.h" #include "pythread.h" #include @@ -1315,7 +1315,7 @@ faulthandler_init_enable(void) return 0; } -_PyInitError +PyStatus _PyFaulthandler_Init(int enable) { #ifdef HAVE_SIGALTSTACK @@ -1340,17 +1340,17 @@ _PyFaulthandler_Init(int enable) thread.cancel_event = PyThread_allocate_lock(); thread.running = PyThread_allocate_lock(); if (!thread.cancel_event || !thread.running) { - return _Py_INIT_ERR("failed to allocate locks for faulthandler"); + return _PyStatus_ERR("failed to allocate locks for faulthandler"); } PyThread_acquire_lock(thread.cancel_event, 1); #endif if (enable) { if (faulthandler_init_enable() < 0) { - return _Py_INIT_ERR("failed to enable faulthandler"); + return _PyStatus_ERR("failed to enable faulthandler"); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } void _PyFaulthandler_Fini(void) diff --git a/Modules/getpath.c b/Modules/getpath.c index 3dcfcef..5f80738 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1,7 +1,7 @@ /* Return the initial module search path. */ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "osdefs.h" #include "pycore_fileutils.h" #include "pycore_pathconfig.h" @@ -115,10 +115,10 @@ extern "C" { #define DECODE_LOCALE_ERR(NAME, LEN) \ ((LEN) == (size_t)-2) \ - ? _Py_INIT_ERR("cannot decode " NAME) \ - : _Py_INIT_NO_MEMORY() + ? _PyStatus_ERR("cannot decode " NAME) \ + : _PyStatus_NO_MEMORY() -#define PATHLEN_ERR() _Py_INIT_ERR("path configuration: path too long") +#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long") typedef struct { wchar_t *path_env; /* PATH environment variable */ @@ -236,7 +236,7 @@ isdir(wchar_t *filename) /* Add a path component, by appending stuff to buffer. buflen: 'buffer' length in characters including trailing NUL. */ -static _PyInitError +static PyStatus joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen) { size_t n, k; @@ -261,7 +261,7 @@ joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen) wcsncpy(buffer+n, stuff, k); buffer[n+k] = '\0'; - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -280,7 +280,7 @@ safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n) /* copy_absolute requires that path be allocated at least 'pathlen' characters (including trailing NUL). */ -static _PyInitError +static PyStatus copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen) { if (p[0] == SEP) { @@ -294,38 +294,38 @@ copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen) if (safe_wcscpy(path, p, pathlen) < 0) { return PATHLEN_ERR(); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } if (p[0] == '.' && p[1] == SEP) { p += 2; } - _PyInitError err = joinpath(path, p, pathlen); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = joinpath(path, p, pathlen); + if (_PyStatus_EXCEPTION(status)) { + return status; } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* path_len: path length in characters including trailing NUL */ -static _PyInitError +static PyStatus absolutize(wchar_t *path, size_t path_len) { if (path[0] == SEP) { - return _Py_INIT_OK(); + return _PyStatus_OK(); } wchar_t abs_path[MAXPATHLEN+1]; - _PyInitError err = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path)); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path)); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (safe_wcscpy(path, abs_path, path_len) < 0) { return PATHLEN_ERR(); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -335,14 +335,14 @@ absolutize(wchar_t *path, size_t path_len) #endif /* pathlen: 'path' length in characters including trailing NUL */ -static _PyInitError +static PyStatus add_exe_suffix(wchar_t *progpath, size_t progpathlen) { /* Check for already have an executable suffix */ size_t n = wcslen(progpath); size_t s = wcslen(EXE_SUFFIX); if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) { - return _Py_INIT_OK(); + return _PyStatus_OK(); } if (n + s >= progpathlen) { @@ -356,7 +356,7 @@ add_exe_suffix(wchar_t *progpath, size_t progpathlen) progpath[n] = '\0'; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } #endif @@ -364,43 +364,43 @@ add_exe_suffix(wchar_t *progpath, size_t progpathlen) /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ -static _PyInitError -search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, +static PyStatus +search_for_prefix(const PyConfig *config, PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len, int *found) { - _PyInitError err; + PyStatus status; size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ - if (core_config->home) { - if (safe_wcscpy(prefix, core_config->home, prefix_len) < 0) { + if (config->home) { + if (safe_wcscpy(prefix, config->home, prefix_len) < 0) { return PATHLEN_ERR(); } wchar_t *delim = wcschr(prefix, DELIM); if (delim) { *delim = L'\0'; } - err = joinpath(prefix, calculate->lib_python, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, calculate->lib_python, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(prefix, LANDMARK, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, LANDMARK, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } *found = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Check to see if argv[0] is in the build directory */ if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(prefix, L"Modules/Setup.local", prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, L"Modules/Setup.local", prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (isfile(prefix)) { @@ -410,48 +410,48 @@ search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(prefix, vpath, prefix_len); + status = joinpath(prefix, vpath, prefix_len); PyMem_RawFree(vpath); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(prefix, L"Lib", prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, L"Lib", prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(prefix, LANDMARK, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, LANDMARK, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (ismodule(prefix, prefix_len)) { *found = -1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } } } /* Search from argv0_path, until root is found */ - err = copy_absolute(prefix, calculate->argv0_path, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = copy_absolute(prefix, calculate->argv0_path, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } do { n = wcslen(prefix); - err = joinpath(prefix, calculate->lib_python, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, calculate->lib_python, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(prefix, LANDMARK, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, LANDMARK, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (ismodule(prefix, prefix_len)) { *found = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } prefix[n] = L'\0'; reduce(prefix); @@ -461,59 +461,59 @@ search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(prefix, calculate->lib_python, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, calculate->lib_python, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(prefix, LANDMARK, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, LANDMARK, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (ismodule(prefix, prefix_len)) { *found = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Fail */ *found = 0; - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError -calculate_prefix(const _PyCoreConfig *core_config, +static PyStatus +calculate_prefix(const PyConfig *config, PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len) { - _PyInitError err; + PyStatus status; - err = search_for_prefix(core_config, calculate, prefix, prefix_len, + status = search_for_prefix(config, calculate, prefix, prefix_len, &calculate->prefix_found); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } if (!calculate->prefix_found) { - if (core_config->pathconfig_warnings) { + if (config->pathconfig_warnings) { fprintf(stderr, "Could not find platform independent libraries \n"); } if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(prefix, calculate->lib_python, prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(prefix, calculate->lib_python, prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } } else { reduce(prefix); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len) { @@ -536,45 +536,45 @@ calculate_reduce_prefix(PyCalculatePath *calculate, return PATHLEN_ERR(); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* search_for_exec_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ -static _PyInitError -search_for_exec_prefix(const _PyCoreConfig *core_config, +static PyStatus +search_for_exec_prefix(const PyConfig *config, PyCalculatePath *calculate, wchar_t *exec_prefix, size_t exec_prefix_len, int *found) { - _PyInitError err; + PyStatus status; size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ - if (core_config->home) { - wchar_t *delim = wcschr(core_config->home, DELIM); + if (config->home) { + wchar_t *delim = wcschr(config->home, DELIM); if (delim) { if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) { return PATHLEN_ERR(); } } else { - if (safe_wcscpy(exec_prefix, core_config->home, exec_prefix_len) < 0) { + if (safe_wcscpy(exec_prefix, config->home, exec_prefix_len) < 0) { return PATHLEN_ERR(); } } - err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } *found = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Check to see if argv[0] is in the build directory. "pybuilddir.txt" @@ -583,9 +583,9 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (isfile(exec_prefix)) { @@ -609,36 +609,36 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(exec_prefix, pybuilddir, exec_prefix_len); + status = joinpath(exec_prefix, pybuilddir, exec_prefix_len); PyMem_RawFree(pybuilddir ); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } *found = -1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } } /* Search from argv0_path, until root is found */ - err = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } do { n = wcslen(exec_prefix); - err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (isdir(exec_prefix)) { *found = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } exec_prefix[n] = L'\0'; reduce(exec_prefix); @@ -648,58 +648,58 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (isdir(exec_prefix)) { *found = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Fail */ *found = 0; - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError -calculate_exec_prefix(const _PyCoreConfig *core_config, +static PyStatus +calculate_exec_prefix(const PyConfig *config, PyCalculatePath *calculate, wchar_t *exec_prefix, size_t exec_prefix_len) { - _PyInitError err; + PyStatus status; - err = search_for_exec_prefix(core_config, calculate, + status = search_for_exec_prefix(config, calculate, exec_prefix, exec_prefix_len, &calculate->exec_prefix_found); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } if (!calculate->exec_prefix_found) { - if (core_config->pathconfig_warnings) { + if (config->pathconfig_warnings) { fprintf(stderr, "Could not find platform dependent libraries \n"); } if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) { return PATHLEN_ERR(); } - err = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } } /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix, size_t exec_prefix_len) { @@ -716,15 +716,15 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, return PATHLEN_ERR(); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError -calculate_program_full_path(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, _PyPathConfig *config) +static PyStatus +calculate_program_full_path(const PyConfig *config, + PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - _PyInitError err; + PyStatus status; wchar_t program_full_path[MAXPATHLEN + 1]; const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path); memset(program_full_path, 0, sizeof(program_full_path)); @@ -743,8 +743,8 @@ calculate_program_full_path(const _PyCoreConfig *core_config, * other way to find a directory to start the search from. If * $PATH isn't exported, you lose. */ - if (wcschr(core_config->program_name, SEP)) { - if (safe_wcscpy(program_full_path, core_config->program_name, + if (wcschr(config->program_name, SEP)) { + if (safe_wcscpy(program_full_path, config->program_name, program_full_path_len) < 0) { return PATHLEN_ERR(); } @@ -795,10 +795,10 @@ calculate_program_full_path(const _PyCoreConfig *core_config, } } - err = joinpath(program_full_path, core_config->program_name, + status = joinpath(program_full_path, config->program_name, program_full_path_len); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } if (isxfile(program_full_path)) { @@ -816,9 +816,9 @@ calculate_program_full_path(const _PyCoreConfig *core_config, program_full_path[0] = '\0'; } if (program_full_path[0] != SEP && program_full_path[0] != '\0') { - err = absolutize(program_full_path, program_full_path_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = absolutize(program_full_path, program_full_path_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } } #if defined(__CYGWIN__) || defined(__MINGW32__) @@ -828,22 +828,22 @@ calculate_program_full_path(const _PyCoreConfig *core_config, * path (bpo-28441). */ if (program_full_path[0] != '\0') { - err = add_exe_suffix(program_full_path, program_full_path_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = add_exe_suffix(program_full_path, program_full_path_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } } #endif - config->program_full_path = _PyMem_RawWcsdup(program_full_path); - if (config->program_full_path == NULL) { - return _Py_INIT_NO_MEMORY(); + pathconfig->program_full_path = _PyMem_RawWcsdup(program_full_path); + if (pathconfig->program_full_path == NULL) { + return _PyStatus_NO_MEMORY(); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path) { const size_t argv0_path_len = Py_ARRAY_LENGTH(calculate->argv0_path); @@ -871,7 +871,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat ** be running the interpreter in the build directory, so we use the ** build-directory-specific logic to find Lib and such. */ - _PyInitError err; + PyStatus status; size_t len; wchar_t* wbuf = Py_DecodeLocale(modPath, &len); if (wbuf == NULL) { @@ -882,15 +882,15 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat return PATHLEN_ERR(); } reduce(calculate->argv0_path); - err = joinpath(calculate->argv0_path, calculate->lib_python, argv0_path_len); - if (_Py_INIT_FAILED(err)) { + status = joinpath(calculate->argv0_path, calculate->lib_python, argv0_path_len); + if (_PyStatus_EXCEPTION(status)) { PyMem_RawFree(wbuf); - return err; + return status; } - err = joinpath(calculate->argv0_path, LANDMARK, argv0_path_len); - if (_Py_INIT_FAILED(err)) { + status = joinpath(calculate->argv0_path, LANDMARK, argv0_path_len); + if (_PyStatus_EXCEPTION(status)) { PyMem_RawFree(wbuf); - return err; + return status; } if (!ismodule(calculate->argv0_path, Py_ARRAY_LENGTH(calculate->argv0_path))) { @@ -925,11 +925,11 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat } else { /* Interpret relative to program_full_path */ - _PyInitError err; + PyStatus status; reduce(calculate->argv0_path); - err = joinpath(calculate->argv0_path, tmpbuffer, argv0_path_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(calculate->argv0_path, tmpbuffer, argv0_path_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } } linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, buflen); @@ -939,7 +939,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat reduce(calculate->argv0_path); /* At this point, argv0_path is guaranteed to be less than MAXPATHLEN bytes long. */ - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -947,10 +947,10 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat executable's directory and then in the parent directory. If found, open it for use when searching for prefixes. */ -static _PyInitError +static PyStatus calculate_read_pyenv(PyCalculatePath *calculate) { - _PyInitError err; + PyStatus status; wchar_t tmpbuffer[MAXPATHLEN+1]; const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer); wchar_t *env_cfg = L"pyvenv.cfg"; @@ -960,9 +960,9 @@ calculate_read_pyenv(PyCalculatePath *calculate) return PATHLEN_ERR(); } - err = joinpath(tmpbuffer, env_cfg, buflen); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(tmpbuffer, env_cfg, buflen); + if (_PyStatus_EXCEPTION(status)) { + return status; } env_file = _Py_wfopen(tmpbuffer, L"r"); if (env_file == NULL) { @@ -970,9 +970,9 @@ calculate_read_pyenv(PyCalculatePath *calculate) reduce(tmpbuffer); reduce(tmpbuffer); - err = joinpath(tmpbuffer, env_cfg, buflen); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(tmpbuffer, env_cfg, buflen); + if (_PyStatus_EXCEPTION(status)) { + return status; } env_file = _Py_wfopen(tmpbuffer, L"r"); @@ -982,7 +982,7 @@ calculate_read_pyenv(PyCalculatePath *calculate) } if (env_file == NULL) { - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Look for a 'home' variable and set argv0_path to it, if found */ @@ -993,14 +993,14 @@ calculate_read_pyenv(PyCalculatePath *calculate) } } fclose(env_file); - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) { - _PyInitError err; + PyStatus status; const size_t zip_path_len = Py_ARRAY_LENGTH(calculate->zip_path); if (safe_wcscpy(calculate->zip_path, prefix, zip_path_len) < 0) { return PATHLEN_ERR(); @@ -1016,29 +1016,29 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) return PATHLEN_ERR(); } } - err = joinpath(calculate->zip_path, L"lib/python00.zip", zip_path_len); - if (_Py_INIT_FAILED(err)) { - return err; + status = joinpath(calculate->zip_path, L"lib/python00.zip", zip_path_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* Replace "00" with version */ size_t bufsz = wcslen(calculate->zip_path); calculate->zip_path[bufsz - 6] = VERSION[0]; calculate->zip_path[bufsz - 5] = VERSION[2]; - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError -calculate_module_search_path(const _PyCoreConfig *core_config, +static PyStatus +calculate_module_search_path(const PyConfig *config, PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, - _PyPathConfig *config) + _PyPathConfig *pathconfig) { /* Calculate size of return buffer */ size_t bufsz = 0; - if (core_config->module_search_path_env != NULL) { - bufsz += wcslen(core_config->module_search_path_env) + 1; + if (config->pythonpath_env != NULL) { + bufsz += wcslen(config->pythonpath_env) + 1; } wchar_t *defpath = calculate->pythonpath; @@ -1067,13 +1067,13 @@ calculate_module_search_path(const _PyCoreConfig *core_config, /* Allocate the buffer */ wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); if (buf == NULL) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } buf[0] = '\0'; /* Run-time value of $PYTHONPATH goes first */ - if (core_config->module_search_path_env) { - wcscpy(buf, core_config->module_search_path_env); + if (config->pythonpath_env) { + wcscpy(buf, config->pythonpath_env); wcscat(buf, delimiter); } @@ -1115,14 +1115,14 @@ calculate_module_search_path(const _PyCoreConfig *core_config, /* Finally, on goes the directory for dynamic-load modules */ wcscat(buf, exec_prefix); - config->module_search_path = buf; - return _Py_INIT_OK(); + pathconfig->module_search_path = buf; + return _PyStatus_OK(); } -static _PyInitError +static PyStatus calculate_init(PyCalculatePath *calculate, - const _PyCoreConfig *core_config) + const PyConfig *config) { size_t len; const char *path = getenv("PATH"); @@ -1149,7 +1149,7 @@ calculate_init(PyCalculatePath *calculate, if (!calculate->lib_python) { return DECODE_LOCALE_ERR("EXEC_PREFIX define", len); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -1164,108 +1164,108 @@ calculate_free(PyCalculatePath *calculate) } -static _PyInitError -calculate_path_impl(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, _PyPathConfig *config) +static PyStatus +calculate_path_impl(const PyConfig *config, + PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - _PyInitError err; + PyStatus status; - err = calculate_program_full_path(core_config, calculate, config); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_program_full_path(config, calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = calculate_argv0_path(calculate, config->program_full_path); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_argv0_path(calculate, pathconfig->program_full_path); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = calculate_read_pyenv(calculate); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_read_pyenv(calculate); + if (_PyStatus_EXCEPTION(status)) { + return status; } wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - err = calculate_prefix(core_config, calculate, + status = calculate_prefix(config, calculate, prefix, Py_ARRAY_LENGTH(prefix)); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = calculate_zip_path(calculate, prefix); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_zip_path(calculate, prefix); + if (_PyStatus_EXCEPTION(status)) { + return status; } wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - err = calculate_exec_prefix(core_config, calculate, + status = calculate_exec_prefix(config, calculate, exec_prefix, Py_ARRAY_LENGTH(exec_prefix)); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } if ((!calculate->prefix_found || !calculate->exec_prefix_found) && - core_config->pathconfig_warnings) + config->pathconfig_warnings) { fprintf(stderr, "Consider setting $PYTHONHOME to [:]\n"); } - err = calculate_module_search_path(core_config, calculate, - prefix, exec_prefix, config); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_module_search_path(config, calculate, + prefix, exec_prefix, pathconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix)); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix)); + if (_PyStatus_EXCEPTION(status)) { + return status; } - config->prefix = _PyMem_RawWcsdup(prefix); - if (config->prefix == NULL) { - return _Py_INIT_NO_MEMORY(); + pathconfig->prefix = _PyMem_RawWcsdup(prefix); + if (pathconfig->prefix == NULL) { + return _PyStatus_NO_MEMORY(); } - err = calculate_reduce_exec_prefix(calculate, + status = calculate_reduce_exec_prefix(calculate, exec_prefix, Py_ARRAY_LENGTH(exec_prefix)); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyStatus_EXCEPTION(status)) { + return status; } - config->exec_prefix = _PyMem_RawWcsdup(exec_prefix); - if (config->exec_prefix == NULL) { - return _Py_INIT_NO_MEMORY(); + pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix); + if (pathconfig->exec_prefix == NULL) { + return _PyStatus_NO_MEMORY(); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError -_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config) +PyStatus +_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) { - _PyInitError err; + PyStatus status; PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - err = calculate_init(&calculate, core_config); - if (_Py_INIT_FAILED(err)) { + status = calculate_init(&calculate, config); + if (_PyStatus_EXCEPTION(status)) { goto done; } - err = calculate_path_impl(core_config, &calculate, config); - if (_Py_INIT_FAILED(err)) { + status = calculate_path_impl(config, &calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { goto done; } - err = _Py_INIT_OK(); + status = _PyStatus_OK(); done: calculate_free(&calculate); - return err; + return status; } #ifdef __cplusplus diff --git a/Modules/main.c b/Modules/main.c index 08fb0e0..6b9406f 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1,7 +1,7 @@ /* Python interpreter main program */ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" #include "pycore_pystate.h" @@ -33,14 +33,14 @@ extern "C" { /* --- pymain_init() ---------------------------------------------- */ -static _PyInitError +static PyStatus pymain_init(const _PyArgv *args) { - _PyInitError err; + PyStatus status; - err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* 754 requires that FP exceptions run in "no stop" mode by default, @@ -52,29 +52,36 @@ pymain_init(const _PyArgv *args) fedisableexcept(FE_OVERFLOW); #endif - _PyPreConfig preconfig; - _PyPreConfig_InitPythonConfig(&preconfig); - err = _Py_PreInitializeFromPyArgv(&preconfig, args); - if (_Py_INIT_FAILED(err)) { - return err; + PyPreConfig preconfig; + PyPreConfig_InitPythonConfig(&preconfig); + status = _Py_PreInitializeFromPyArgv(&preconfig, args); + if (_PyStatus_EXCEPTION(status)) { + return status; } - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_Py_INIT_FAILED(err)) { - return err; + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* pass NULL as the config: config is read from command line arguments, environment variables, configuration files */ if (args->use_bytes_argv) { - return _Py_InitializeFromArgs(&config, - args->argc, args->bytes_argv); + status = PyConfig_SetBytesArgv(&config, args->argc, args->bytes_argv); } else { - return _Py_InitializeFromWideArgs(&config, - args->argc, args->wchar_argv); + status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv); } + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = Py_InitializeFromConfig(&config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } @@ -82,13 +89,17 @@ pymain_init(const _PyArgv *args) /* Non-zero if filename, command (-c) or module (-m) is set on the command line */ -#define RUN_CODE(config) \ - (config->run_command != NULL || config->run_filename != NULL \ - || config->run_module != NULL) +static inline int config_run_code(const PyConfig *config) +{ + return (config->run_command != NULL + || config->run_filename != NULL + || config->run_module != NULL); +} + /* Return non-zero is stdin is a TTY or if -i command line option is used */ static int -stdin_is_interactive(const _PyCoreConfig *config) +stdin_is_interactive(const PyConfig *config) { return (isatty(fileno(stdin)) || config->interactive); } @@ -181,13 +192,13 @@ pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0) static void -pymain_header(const _PyCoreConfig *config) +pymain_header(const PyConfig *config) { if (config->quiet) { return; } - if (!config->verbose && (RUN_CODE(config) || !stdin_is_interactive(config))) { + if (!config->verbose && (config_run_code(config) || !stdin_is_interactive(config))) { return; } @@ -199,12 +210,12 @@ pymain_header(const _PyCoreConfig *config) static void -pymain_import_readline(const _PyCoreConfig *config) +pymain_import_readline(const PyConfig *config) { if (config->isolated) { return; } - if (!config->inspect && RUN_CODE(config)) { + if (!config->inspect && config_run_code(config)) { return; } if (!isatty(fileno(stdin))) { @@ -293,7 +304,7 @@ pymain_run_module(const wchar_t *modname, int set_argv0) static int -pymain_run_file(_PyCoreConfig *config, PyCompilerFlags *cf) +pymain_run_file(PyConfig *config, PyCompilerFlags *cf) { const wchar_t *filename = config->run_filename; FILE *fp = _Py_wfopen(filename, L"rb"); @@ -362,7 +373,7 @@ pymain_run_file(_PyCoreConfig *config, PyCompilerFlags *cf) static int -pymain_run_startup(_PyCoreConfig *config, PyCompilerFlags *cf, int *exitcode) +pymain_run_startup(PyConfig *config, PyCompilerFlags *cf, int *exitcode) { const char *startup = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP"); if (startup == NULL) { @@ -421,7 +432,7 @@ error: static int -pymain_run_stdin(_PyCoreConfig *config, PyCompilerFlags *cf) +pymain_run_stdin(PyConfig *config, PyCompilerFlags *cf) { if (stdin_is_interactive(config)) { config->inspect = 0; @@ -448,7 +459,7 @@ pymain_run_stdin(_PyCoreConfig *config, PyCompilerFlags *cf) static void -pymain_repl(_PyCoreConfig *config, PyCompilerFlags *cf, int *exitcode) +pymain_repl(PyConfig *config, PyCompilerFlags *cf, int *exitcode) { /* Check this environment variable at the end, to give programs the opportunity to set it from Python. */ @@ -457,7 +468,7 @@ pymain_repl(_PyCoreConfig *config, PyCompilerFlags *cf, int *exitcode) Py_InspectFlag = 1; } - if (!(config->inspect && stdin_is_interactive(config) && RUN_CODE(config))) { + if (!(config->inspect && stdin_is_interactive(config) && config_run_code(config))) { return; } @@ -477,7 +488,7 @@ pymain_run_python(int *exitcode) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); /* pymain_run_stdin() modify the config */ - _PyCoreConfig *config = &interp->core_config; + PyConfig *config = &interp->config; PyObject *main_importer_path = NULL; if (config->run_filename != NULL) { @@ -590,20 +601,20 @@ exit_sigint(void) static void _Py_NO_RETURN -pymain_exit_error(_PyInitError err) +pymain_exit_error(PyStatus status) { - if (_Py_INIT_IS_EXIT(err)) { + if (_PyStatus_IS_EXIT(status)) { /* If it's an error rather than a regular exit, leave Python runtime - alive: _Py_ExitInitError() uses the current exception and use + alive: Py_ExitStatusException() uses the current exception and use sys.stdout in this case. */ pymain_free(); } - _Py_ExitInitError(err); + Py_ExitStatusException(status); } int -_Py_RunMain(void) +Py_RunMain(void) { int exitcode = 0; @@ -628,16 +639,16 @@ _Py_RunMain(void) static int pymain_main(_PyArgv *args) { - _PyInitError err = pymain_init(args); - if (_Py_INIT_IS_EXIT(err)) { + PyStatus status = pymain_init(args); + if (_PyStatus_IS_EXIT(status)) { pymain_free(); - return err.exitcode; + return status.exitcode; } - if (_Py_INIT_FAILED(err)) { - pymain_exit_error(err); + if (_PyStatus_EXCEPTION(status)) { + pymain_exit_error(status); } - return _Py_RunMain(); + return Py_RunMain(); } @@ -654,7 +665,7 @@ Py_Main(int argc, wchar_t **argv) int -_Py_UnixMain(int argc, char **argv) +Py_BytesMain(int argc, char **argv) { _PyArgv args = { .argc = argc, diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 8d5ba54..c7c2831 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -999,7 +999,7 @@ bytearray_repr(PyByteArrayObject *self) static PyObject * bytearray_str(PyObject *op) { - _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (config->bytes_warning) { if (PyErr_WarnEx(PyExc_BytesWarning, "str() on a bytearray instance", 1)) { @@ -1025,7 +1025,7 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op) if (rc < 0) return NULL; if (rc) { - _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (config->bytes_warning && (op == Py_EQ || op == Py_NE)) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytearray and string", 1)) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 41453b2..0a3ed86 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1421,7 +1421,7 @@ bytes_repr(PyObject *op) static PyObject * bytes_str(PyObject *op) { - _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (config->bytes_warning) { if (PyErr_WarnEx(PyExc_BytesWarning, "str() on a bytes instance", 1)) { @@ -1579,7 +1579,7 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) /* Make sure both arguments are strings. */ if (!(PyBytes_Check(a) && PyBytes_Check(b))) { - _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (config->bytes_warning && (op == Py_EQ || op == Py_NE)) { rc = PyObject_IsInstance((PyObject*)a, (PyObject*)&PyUnicode_Type); diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 4dad0b2..8456a8f 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -6,7 +6,7 @@ #define PY_SSIZE_T_CLEAN #include -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_object.h" #include "pycore_pymem.h" #include "pycore_pystate.h" @@ -2499,13 +2499,13 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning, #endif #endif /* MS_WINDOWS */ -_PyInitError +PyStatus _PyExc_Init(void) { #define PRE_INIT(TYPE) \ if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \ if (PyType_Ready(&_PyExc_ ## TYPE) < 0) { \ - return _Py_INIT_ERR("exceptions bootstrapping error."); \ + return _PyStatus_ERR("exceptions bootstrapping error."); \ } \ Py_INCREF(PyExc_ ## TYPE); \ } @@ -2515,7 +2515,7 @@ _PyExc_Init(void) PyObject *_code = PyLong_FromLong(CODE); \ assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \ if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) \ - return _Py_INIT_ERR("errmap insertion problem."); \ + return _PyStatus_ERR("errmap insertion problem."); \ Py_DECREF(_code); \ } while (0) @@ -2589,14 +2589,14 @@ _PyExc_Init(void) PRE_INIT(TimeoutError); if (preallocate_memerrors() < 0) { - return _Py_INIT_ERR("Could not preallocate MemoryError object"); + return _PyStatus_ERR("Could not preallocate MemoryError object"); } /* Add exceptions to errnomap */ if (!errnomap) { errnomap = PyDict_New(); if (!errnomap) { - return _Py_INIT_ERR("Cannot allocate map from errnos to OSError subclasses"); + return _PyStatus_ERR("Cannot allocate map from errnos to OSError subclasses"); } } @@ -2622,7 +2622,7 @@ _PyExc_Init(void) ADD_ERRNO(ProcessLookupError, ESRCH); ADD_ERRNO(TimeoutError, ETIMEDOUT); - return _Py_INIT_OK(); + return _PyStatus_OK(); #undef PRE_INIT #undef ADD_ERRNO @@ -2630,12 +2630,12 @@ _PyExc_Init(void) /* Add exception types to the builtins module */ -_PyInitError +PyStatus _PyBuiltins_AddExceptions(PyObject *bltinmod) { #define POST_INIT(TYPE) \ if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) { \ - return _Py_INIT_ERR("Module dictionary insertion problem."); \ + return _PyStatus_ERR("Module dictionary insertion problem."); \ } #define INIT_ALIAS(NAME, TYPE) \ @@ -2644,7 +2644,7 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod) Py_XDECREF(PyExc_ ## NAME); \ PyExc_ ## NAME = PyExc_ ## TYPE; \ if (PyDict_SetItemString(bdict, # NAME, PyExc_ ## NAME)) { \ - return _Py_INIT_ERR("Module dictionary insertion problem."); \ + return _PyStatus_ERR("Module dictionary insertion problem."); \ } \ } while (0) @@ -2652,7 +2652,7 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod) bdict = PyModule_GetDict(bltinmod); if (bdict == NULL) { - return _Py_INIT_ERR("exceptions bootstrapping error."); + return _PyStatus_ERR("exceptions bootstrapping error."); } POST_INIT(BaseException); @@ -2729,7 +2729,7 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod) POST_INIT(ProcessLookupError); POST_INIT(TimeoutError); - return _Py_INIT_OK(); + return _PyStatus_OK(); #undef POST_INIT #undef INIT_ALIAS diff --git a/Objects/listobject.c b/Objects/listobject.c index 3185957..b210c00 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -104,7 +104,7 @@ static void show_alloc(void) { PyInterpreterState *interp = _PyInterpreterState_Get(); - if (!interp->core_config.show_alloc_count) { + if (!interp->config.show_alloc_count) { return; } diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index e570107c..20e7d44 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -590,7 +590,7 @@ _PyModule_ClearDict(PyObject *d) Py_ssize_t pos; PyObject *key, *value; - int verbose = _PyInterpreterState_GET_UNSAFE()->core_config.verbose; + int verbose = _PyInterpreterState_GET_UNSAFE()->config.verbose; /* First, clear only names starting with a single underscore */ pos = 0; @@ -677,7 +677,7 @@ module___init___impl(PyModuleObject *self, PyObject *name, PyObject *doc) static void module_dealloc(PyModuleObject *m) { - int verbose = _PyInterpreterState_GET_UNSAFE()->core_config.verbose; + int verbose = _PyInterpreterState_GET_UNSAFE()->config.verbose; PyObject_GC_UnTrack(m); if (verbose && m->md_name) { diff --git a/Objects/object.c b/Objects/object.c index 6d79165..270716f 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2,7 +2,7 @@ /* Generic object operations; and implementation of None */ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_object.h" #include "pycore_pystate.h" #include "pycore_context.h" @@ -124,7 +124,7 @@ void _Py_dump_counts(FILE* f) { PyInterpreterState *interp = _PyInterpreterState_Get(); - if (!interp->core_config.show_alloc_count) { + if (!interp->config.show_alloc_count) { return; } @@ -1767,13 +1767,13 @@ PyObject _Py_NotImplementedStruct = { 1, &_PyNotImplemented_Type }; -_PyInitError +PyStatus _PyTypes_Init(void) { #define INIT_TYPE(TYPE, NAME) \ do { \ if (PyType_Ready(TYPE) < 0) { \ - return _Py_INIT_ERR("Can't initialize " NAME " type"); \ + return _PyStatus_ERR("Can't initialize " NAME " type"); \ } \ } while (0) @@ -1843,7 +1843,7 @@ _PyTypes_Init(void) INIT_TYPE(&PyCoro_Type, "coroutine"); INIT_TYPE(&_PyCoroWrapper_Type, "coroutine wrapper"); INIT_TYPE(&_PyInterpreterID_Type, "interpreter ID"); - return _Py_INIT_OK(); + return _PyStatus_OK(); #undef INIT_TYPE } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index dc1d0e5..72556ad 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -46,7 +46,7 @@ static void show_track(void) { PyInterpreterState *interp = _PyInterpreterState_Get(); - if (!interp->core_config.show_alloc_count) { + if (!interp->config.show_alloc_count) { return; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 0aa5e4a..0fe7b56 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -40,7 +40,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_fileutils.h" #include "pycore_object.h" #include "pycore_pylifecycle.h" @@ -3549,9 +3549,9 @@ PyUnicode_EncodeFSDefault(PyObject *unicode) interp->fs_codec.errors); } else { - const _PyCoreConfig *config = &interp->core_config; + const wchar_t *filesystem_errors = interp->config.filesystem_errors; _Py_error_handler errors; - errors = get_error_handler_wide(config->filesystem_errors); + errors = get_error_handler_wide(filesystem_errors); assert(errors != _Py_ERROR_UNKNOWN); return unicode_encode_utf8(unicode, errors, NULL); } @@ -3567,9 +3567,9 @@ PyUnicode_EncodeFSDefault(PyObject *unicode) interp->fs_codec.errors); } else { - const _PyCoreConfig *config = &interp->core_config; + const wchar_t *filesystem_errors = interp->config.filesystem_errors; _Py_error_handler errors; - errors = get_error_handler_wide(config->filesystem_errors); + errors = get_error_handler_wide(filesystem_errors); assert(errors != _Py_ERROR_UNKNOWN); return unicode_encode_locale(unicode, errors, 0); } @@ -3787,9 +3787,9 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) NULL); } else { - const _PyCoreConfig *config = &interp->core_config; + const wchar_t *filesystem_errors = interp->config.filesystem_errors; _Py_error_handler errors; - errors = get_error_handler_wide(config->filesystem_errors); + errors = get_error_handler_wide(filesystem_errors); assert(errors != _Py_ERROR_UNKNOWN); return unicode_decode_utf8(s, size, errors, NULL, NULL); } @@ -3805,9 +3805,9 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) interp->fs_codec.errors); } else { - const _PyCoreConfig *config = &interp->core_config; + const wchar_t *filesystem_errors = interp->config.filesystem_errors; _Py_error_handler errors; - errors = get_error_handler_wide(config->filesystem_errors); + errors = get_error_handler_wide(filesystem_errors); return unicode_decode_locale(s, size, errors, 0); } #endif @@ -15200,7 +15200,7 @@ PyTypeObject PyUnicode_Type = { /* Initialize the Unicode implementation */ -_PyInitError +PyStatus _PyUnicode_Init(void) { /* XXX - move this array to unicodectype.c ? */ @@ -15218,12 +15218,12 @@ _PyUnicode_Init(void) /* Init the implementation */ _Py_INCREF_UNICODE_EMPTY(); if (!unicode_empty) { - return _Py_INIT_ERR("Can't create empty string"); + return _PyStatus_ERR("Can't create empty string"); } Py_DECREF(unicode_empty); if (PyType_Ready(&PyUnicode_Type) < 0) { - return _Py_INIT_ERR("Can't initialize unicode type"); + return _PyStatus_ERR("Can't initialize unicode type"); } /* initialize the linebreak bloom filter */ @@ -15232,15 +15232,15 @@ _PyUnicode_Init(void) Py_ARRAY_LENGTH(linebreak)); if (PyType_Ready(&EncodingMapType) < 0) { - return _Py_INIT_ERR("Can't initialize encoding map type"); + return _PyStatus_ERR("Can't initialize encoding map type"); } if (PyType_Ready(&PyFieldNameIter_Type) < 0) { - return _Py_INIT_ERR("Can't initialize field name iterator type"); + return _PyStatus_ERR("Can't initialize field name iterator type"); } if (PyType_Ready(&PyFormatterIter_Type) < 0) { - return _Py_INIT_ERR("Can't initialize formatter iter type"); + return _PyStatus_ERR("Can't initialize formatter iter type"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Finalize the Unicode implementation */ @@ -15718,23 +15718,23 @@ error: } -static _PyInitError +static PyStatus init_stdio_encoding(PyInterpreterState *interp) { /* Update the stdio encoding to the normalized Python codec name. */ - _PyCoreConfig *config = &interp->core_config; + PyConfig *config = &interp->config; if (config_get_codec_name(&config->stdio_encoding) < 0) { - return _Py_INIT_ERR("failed to get the Python codec name " + return _PyStatus_ERR("failed to get the Python codec name " "of the stdio encoding"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } static int init_fs_codec(PyInterpreterState *interp) { - _PyCoreConfig *config = &interp->core_config; + PyConfig *config = &interp->config; _Py_error_handler error_handler; error_handler = get_error_handler_wide(config->filesystem_errors); @@ -15778,31 +15778,31 @@ init_fs_codec(PyInterpreterState *interp) } -static _PyInitError +static PyStatus init_fs_encoding(PyInterpreterState *interp) { /* Update the filesystem encoding to the normalized Python codec name. For example, replace "ANSI_X3.4-1968" (locale encoding) with "ascii" (Python codec name). */ - _PyCoreConfig *config = &interp->core_config; + PyConfig *config = &interp->config; if (config_get_codec_name(&config->filesystem_encoding) < 0) { - return _Py_INIT_ERR("failed to get the Python codec " + return _PyStatus_ERR("failed to get the Python codec " "of the filesystem encoding"); } if (init_fs_codec(interp) < 0) { - return _Py_INIT_ERR("cannot initialize filesystem codec"); + return _PyStatus_ERR("cannot initialize filesystem codec"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError +PyStatus _PyUnicode_InitEncodings(PyInterpreterState *interp) { - _PyInitError err = init_fs_encoding(interp); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = init_fs_encoding(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } return init_stdio_encoding(interp); @@ -15814,7 +15814,7 @@ int _PyUnicode_EnableLegacyWindowsFSEncoding(void) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - _PyCoreConfig *config = &interp->core_config; + PyConfig *config = &interp->config; /* Set the filesystem encoding to mbcs/replace (PEP 529) */ wchar_t *encoding = _PyMem_RawWcsdup(L"mbcs"); diff --git a/PC/getpathp.c b/PC/getpathp.c index 62c42ec..e86cf13 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -80,7 +80,7 @@ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_pystate.h" #include "osdefs.h" #include @@ -272,10 +272,10 @@ typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cch PCWSTR pszPathIn, unsigned long dwFlags); static PPathCchCanonicalizeEx _PathCchCanonicalizeEx; -static _PyInitError canonicalize(wchar_t *buffer, const wchar_t *path) +static PyStatus canonicalize(wchar_t *buffer, const wchar_t *path) { if (buffer == NULL) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } if (_PathCchCanonicalizeEx_Initialized == 0) { @@ -291,15 +291,15 @@ static _PyInitError canonicalize(wchar_t *buffer, const wchar_t *path) if (_PathCchCanonicalizeEx) { if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) { - return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + return _PyStatus_ERR("buffer overflow in getpathp.c's canonicalize()"); } } else { if (!PathCanonicalizeW(buffer, path)) { - return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + return _PyStatus_ERR("buffer overflow in getpathp.c's canonicalize()"); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -529,9 +529,9 @@ _Py_GetDLLPath(void) } -static _PyInitError -get_program_full_path(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, _PyPathConfig *config) +static PyStatus +get_program_full_path(const PyConfig *config, + PyCalculatePath *calculate, _PyPathConfig *pathconfig) { const wchar_t *pyvenv_launcher; wchar_t program_full_path[MAXPATHLEN+1]; @@ -544,19 +544,19 @@ get_program_full_path(const _PyCoreConfig *core_config, wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher); } else if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { /* GetModuleFileName should never fail when passed NULL */ - return _Py_INIT_ERR("Cannot determine program path"); + return _PyStatus_ERR("Cannot determine program path"); } - config->program_full_path = PyMem_RawMalloc( + pathconfig->program_full_path = PyMem_RawMalloc( sizeof(wchar_t) * (MAXPATHLEN + 1)); - return canonicalize(config->program_full_path, + return canonicalize(pathconfig->program_full_path, program_full_path); } static int -read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path) +read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path) { FILE *sp_file = _Py_wfopen(path, L"r"); if (sp_file == NULL) { @@ -565,8 +565,8 @@ read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path) wcscpy_s(prefix, MAXPATHLEN+1, path); reduce(prefix); - config->isolated = 1; - config->site_import = 0; + pathconfig->isolated = 1; + pathconfig->site_import = 0; size_t bufsiz = MAXPATHLEN; size_t prefixlen = wcslen(prefix); @@ -594,7 +594,7 @@ read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path) } if (strcmp(line, "import site") == 0) { - config->site_import = 1; + pathconfig->site_import = 1; continue; } else if (strncmp(line, "import ", 7) == 0) { @@ -642,7 +642,7 @@ read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path) } fclose(sp_file); - config->module_search_path = buf; + pathconfig->module_search_path = buf; return 1; error: @@ -654,25 +654,25 @@ error: static void calculate_init(PyCalculatePath *calculate, - const _PyCoreConfig *core_config) + const PyConfig *config) { - calculate->home = core_config->home; + calculate->home = config->home; calculate->path_env = _wgetenv(L"PATH"); } static int -get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) +get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig) { - if (config->dll_path[0]) { - if (!change_ext(spbuffer, config->dll_path, L"._pth") && + if (pathconfig->dll_path[0]) { + if (!change_ext(spbuffer, pathconfig->dll_path, L"._pth") && exists(spbuffer)) { return 1; } } - if (config->program_full_path[0]) { - if (!change_ext(spbuffer, config->program_full_path, L"._pth") && + if (pathconfig->program_full_path[0]) { + if (!change_ext(spbuffer, pathconfig->program_full_path, L"._pth") && exists(spbuffer)) { return 1; @@ -683,15 +683,15 @@ get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) static int -calculate_pth_file(_PyPathConfig *config, wchar_t *prefix) +calculate_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix) { wchar_t spbuffer[MAXPATHLEN+1]; - if (!get_pth_filename(spbuffer, config)) { + if (!get_pth_filename(spbuffer, pathconfig)) { return 0; } - return read_pth_file(config, prefix, spbuffer); + return read_pth_file(pathconfig, prefix, spbuffer); } @@ -735,7 +735,7 @@ calculate_pyvenv_file(PyCalculatePath *calculate) } -#define INIT_ERR_BUFFER_OVERFLOW() _Py_INIT_ERR("buffer overflow") +#define INIT_ERR_BUFFER_OVERFLOW() _PyStatus_ERR("buffer overflow") static void @@ -760,9 +760,9 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) } -static _PyInitError -calculate_module_search_path(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, _PyPathConfig *config, +static PyStatus +calculate_module_search_path(const PyConfig *config, + PyCalculatePath *calculate, _PyPathConfig *pathconfig, wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; @@ -772,7 +772,7 @@ calculate_module_search_path(const _PyCoreConfig *core_config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (core_config->module_search_path_env != NULL || + int skipdefault = (config->pythonpath_env != NULL || calculate->home != NULL || calculate->machine_path != NULL || calculate->user_path != NULL); @@ -811,8 +811,8 @@ calculate_module_search_path(const _PyCoreConfig *core_config, bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; - if (core_config->module_search_path_env != NULL) { - bufsz += wcslen(core_config->module_search_path_env) + 1; + if (config->pythonpath_env != NULL) { + bufsz += wcslen(config->pythonpath_env) + 1; } wchar_t *buf, *start_buf; @@ -820,21 +820,21 @@ calculate_module_search_path(const _PyCoreConfig *core_config, if (buf == NULL) { /* We can't exit, so print a warning and limp along */ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); - if (core_config->module_search_path_env) { + if (config->pythonpath_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); - config->module_search_path = core_config->module_search_path_env; + pathconfig->module_search_path = config->pythonpath_env; } else { fprintf(stderr, "Using default static path.\n"); - config->module_search_path = PYTHONPATH; + pathconfig->module_search_path = PYTHONPATH; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } start_buf = buf; - if (core_config->module_search_path_env) { + if (config->pythonpath_env) { if (wcscpy_s(buf, bufsz - (buf - start_buf), - core_config->module_search_path_env)) { + config->pythonpath_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -941,38 +941,38 @@ calculate_module_search_path(const _PyCoreConfig *core_config, } } - config->module_search_path = start_buf; - return _Py_INIT_OK(); + pathconfig->module_search_path = start_buf; + return _PyStatus_OK(); } -static _PyInitError -calculate_path_impl(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, _PyPathConfig *config) +static PyStatus +calculate_path_impl(const PyConfig *config, + PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - _PyInitError err; + PyStatus status; - assert(config->dll_path == NULL); + assert(pathconfig->dll_path == NULL); - config->dll_path = _Py_GetDLLPath(); - if (config->dll_path == NULL) { - return _Py_INIT_NO_MEMORY(); + pathconfig->dll_path = _Py_GetDLLPath(); + if (pathconfig->dll_path == NULL) { + return _PyStatus_NO_MEMORY(); } - err = get_program_full_path(core_config, calculate, config); - if (_Py_INIT_FAILED(err)) { - return err; + status = get_program_full_path(config, calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */ - wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_full_path); + wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, pathconfig->program_full_path); reduce(calculate->argv0_path); wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); /* Search for a sys.path file */ - if (calculate_pth_file(config, prefix)) { + if (calculate_pth_file(pathconfig, prefix)) { goto done; } @@ -980,27 +980,27 @@ calculate_path_impl(const _PyCoreConfig *core_config, /* Calculate zip archive path from DLL or exe path */ change_ext(calculate->zip_path, - config->dll_path[0] ? config->dll_path : config->program_full_path, + pathconfig->dll_path[0] ? pathconfig->dll_path : pathconfig->program_full_path, L".zip"); calculate_home_prefix(calculate, prefix); - err = calculate_module_search_path(core_config, calculate, config, prefix); - if (_Py_INIT_FAILED(err)) { - return err; + status = calculate_module_search_path(config, calculate, pathconfig, prefix); + if (_PyStatus_EXCEPTION(status)) { + return status; } done: - config->prefix = _PyMem_RawWcsdup(prefix); - if (config->prefix == NULL) { - return _Py_INIT_NO_MEMORY(); + pathconfig->prefix = _PyMem_RawWcsdup(prefix); + if (pathconfig->prefix == NULL) { + return _PyStatus_NO_MEMORY(); } - config->exec_prefix = _PyMem_RawWcsdup(prefix); - if (config->exec_prefix == NULL) { - return _Py_INIT_NO_MEMORY(); + pathconfig->exec_prefix = _PyMem_RawWcsdup(prefix); + if (pathconfig->exec_prefix == NULL) { + return _PyStatus_NO_MEMORY(); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -1012,24 +1012,24 @@ calculate_free(PyCalculatePath *calculate) } -_PyInitError -_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config) +PyStatus +_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) { PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - calculate_init(&calculate, core_config); + calculate_init(&calculate, config); - _PyInitError err = calculate_path_impl(core_config, &calculate, config); - if (_Py_INIT_FAILED(err)) { + PyStatus status = calculate_path_impl(config, &calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { goto done; } - err = _Py_INIT_OK(); + status = _PyStatus_OK(); done: calculate_free(&calculate); - return err; + return status; } diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index db691cd..329f9fe 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -127,9 +127,9 @@ - + @@ -161,11 +161,11 @@ - + @@ -420,7 +420,6 @@ - @@ -438,6 +437,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index dba47e9..d80d05f 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -84,15 +84,15 @@ Include - - Include - Include Include + + Include + Include @@ -186,9 +186,6 @@ Include - - Include - Include @@ -201,6 +198,9 @@ Include + + Include + Include @@ -920,9 +920,6 @@ Python - - Python - Python @@ -977,6 +974,9 @@ Python + + Python + Python diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 8cf44d3..13375b0 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -36,7 +36,7 @@ main(int argc, char *argv[]) const char *name, *inpath, *outpath; char buf[100]; FILE *infile = NULL, *outfile = NULL; - struct _Py_stat_struct status; + struct _Py_stat_struct stat; size_t text_size, data_size, i, n; char *text = NULL; unsigned char *data; @@ -56,11 +56,11 @@ main(int argc, char *argv[]) fprintf(stderr, "cannot open '%s' for reading\n", inpath); goto error; } - if (_Py_fstat_noraise(fileno(infile), &status)) { + if (_Py_fstat_noraise(fileno(infile), &stat)) { fprintf(stderr, "cannot fstat '%s'\n", inpath); goto error; } - text_size = (size_t)status.st_size; + text_size = (size_t)stat.st_size; text = (char *) malloc(text_size + 1); if (text == NULL) { fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size); @@ -76,32 +76,32 @@ main(int argc, char *argv[]) } text[text_size] = '\0'; - _PyInitError err; - _PyCoreConfig config; + PyStatus status; + PyConfig config; - err = _PyCoreConfig_InitIsolatedConfig(&config); - if (_PyInitError_Failed(err)) { - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + status = PyConfig_InitIsolatedConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); } config.site_import = 0; - err = _PyCoreConfig_SetString(&config, &config.program_name, + status = PyConfig_SetString(&config, &config.program_name, L"./_freeze_importlib"); - if (_PyInitError_Failed(err)) { - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); } /* Don't install importlib, since it could execute outdated bytecode. */ config._install_importlib = 0; config._init_main = 0; - err = _Py_InitializeFromConfig(&config); - _PyCoreConfig_Clear(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } sprintf(buf, "", name); diff --git a/Programs/_testembed.c b/Programs/_testembed.c index de1c587..3e1210e 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -4,7 +4,7 @@ #endif #include -#include "pycore_coreconfig.h" /* FIXME: PEP 587 makes these functions public */ +#include "pycore_initconfig.h" /* FIXME: PEP 587 makes these functions public */ #include #include "pythread.h" #include @@ -328,25 +328,25 @@ static int test_init_initialize_config(void) static int check_init_compat_config(int preinit) { - _PyInitError err; + PyStatus status; if (preinit) { - _PyPreConfig preconfig; + PyPreConfig preconfig; _PyPreConfig_InitCompatConfig(&preconfig); - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } } - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + PyConfig config; + _PyConfig_InitCompatConfig(&config); config.program_name = L"./_testembed"; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); @@ -418,9 +418,9 @@ static int test_init_global_config(void) static int test_init_from_config(void) { - _PyInitError err; + PyStatus status; - _PyPreConfig preconfig; + PyPreConfig preconfig; _PyPreConfig_InitCompatConfig(&preconfig); putenv("PYTHONMALLOC=malloc_debug"); @@ -430,14 +430,14 @@ static int test_init_from_config(void) Py_UTF8Mode = 0; preconfig.utf8_mode = 1; - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - /* Test _Py_InitializeFromConfig() */ - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + /* Test Py_InitializeFromConfig() */ + PyConfig config; + _PyConfig_InitCompatConfig(&config); config.install_signal_handlers = 0; /* FIXME: test use_environment */ @@ -481,9 +481,9 @@ static int test_init_from_config(void) config.parse_argv = 1; static wchar_t* xoptions[3] = { - L"core_xoption1=3", - L"core_xoption2=", - L"core_xoption3", + L"xoption1=3", + L"xoption2=", + L"xoption3", }; config.xoptions.length = Py_ARRAY_LENGTH(xoptions); config.xoptions.items = xoptions; @@ -494,7 +494,7 @@ static int test_init_from_config(void) config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions); config.warnoptions.items = warnoptions; - /* FIXME: test module_search_path_env */ + /* FIXME: test pythonpath_env */ /* FIXME: test home */ /* FIXME: test path config: module_search_path .. dll_path */ @@ -553,9 +553,9 @@ static int test_init_from_config(void) Py_FrozenFlag = 0; config.pathconfig_warnings = 0; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -565,12 +565,12 @@ static int test_init_from_config(void) static int check_init_parse_argv(int parse_argv) { - _PyInitError err; + PyStatus status; - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } static wchar_t* argv[] = { @@ -587,9 +587,9 @@ static int check_init_parse_argv(int parse_argv) config.argv.items = argv; config.parse_argv = parse_argv; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -652,20 +652,20 @@ static int test_init_compat_env(void) static int test_init_python_env(void) { - _PyInitError err; + PyStatus status; set_all_env_vars(); - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } config.program_name = L"./_testembed"; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -708,13 +708,13 @@ static int test_init_env_dev_mode_alloc(void) static int test_init_isolated_flag(void) { - _PyInitError err; + PyStatus status; - /* Test _PyCoreConfig.isolated=1 */ - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + /* Test PyConfig.isolated=1 */ + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } Py_IsolatedFlag = 0; @@ -724,9 +724,9 @@ static int test_init_isolated_flag(void) config.program_name = L"./_testembed"; set_all_env_vars(); - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -734,28 +734,28 @@ static int test_init_isolated_flag(void) } -/* _PyPreConfig.isolated=1, _PyCoreConfig.isolated=0 */ +/* PyPreConfig.isolated=1, PyConfig.isolated=0 */ static int test_preinit_isolated1(void) { - _PyInitError err; + PyStatus status; - _PyPreConfig preconfig; + PyPreConfig preconfig; _PyPreConfig_InitCompatConfig(&preconfig); preconfig.isolated = 1; - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + PyConfig config; + _PyConfig_InitCompatConfig(&config); config.program_name = L"./_testembed"; set_all_env_vars(); - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -763,23 +763,23 @@ static int test_preinit_isolated1(void) } -/* _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 */ +/* PyPreConfig.isolated=0, PyConfig.isolated=1 */ static int test_preinit_isolated2(void) { - _PyInitError err; + PyStatus status; - _PyPreConfig preconfig; + PyPreConfig preconfig; _PyPreConfig_InitCompatConfig(&preconfig); preconfig.isolated = 0; - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - /* Test _PyCoreConfig.isolated=1 */ - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + /* Test PyConfig.isolated=1 */ + PyConfig config; + _PyConfig_InitCompatConfig(&config); Py_IsolatedFlag = 0; config.isolated = 1; @@ -788,9 +788,9 @@ static int test_preinit_isolated2(void) config.program_name = L"./_testembed"; set_all_env_vars(); - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -800,10 +800,10 @@ static int test_preinit_isolated2(void) static int test_preinit_dont_parse_argv(void) { - _PyInitError err; + PyStatus status; - _PyPreConfig preconfig; - _PyPreConfig_InitIsolatedConfig(&preconfig); + PyPreConfig preconfig; + PyPreConfig_InitIsolatedConfig(&preconfig); preconfig.isolated = 0; @@ -814,15 +814,15 @@ static int test_preinit_dont_parse_argv(void) L"-X", L"dev", L"-X", L"utf8", L"script.py"}; - err = _Py_PreInitializeFromWideArgs(&preconfig, Py_ARRAY_LENGTH(argv), argv); - if (_PyInitError_Failed(err)) { + status = Py_PreInitializeFromArgs(&preconfig, Py_ARRAY_LENGTH(argv), argv); + if (PyStatus_Exception(status)) { goto failed; } - _PyCoreConfig config; + PyConfig config; - err = _PyCoreConfig_InitIsolatedConfig(&config); - if (_PyInitError_Failed(err)) { + status = PyConfig_InitIsolatedConfig(&config); + if (PyStatus_Exception(status)) { goto failed; } @@ -830,70 +830,70 @@ static int test_preinit_dont_parse_argv(void) /* Pre-initialize implicitly using argv: make sure that -X dev is used to configure the allocation in preinitialization */ - err = _PyCoreConfig_SetWideArgv(&config, Py_ARRAY_LENGTH(argv), argv); - if (_PyInitError_Failed(err)) { + status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv); + if (PyStatus_Exception(status)) { goto failed; } - err = _PyCoreConfig_SetString(&config, &config.program_name, + status = PyConfig_SetString(&config, &config.program_name, L"./_testembed"); - if (_PyInitError_Failed(err)) { + if (PyStatus_Exception(status)) { goto failed; } - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { goto failed; } - _PyCoreConfig_Clear(&config); + PyConfig_Clear(&config); dump_config(); Py_Finalize(); return 0; failed: - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + PyConfig_Clear(&config); + Py_ExitStatusException(status); } static int test_preinit_parse_argv(void) { - _PyInitError err; - _PyCoreConfig config; + PyStatus status; + PyConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { goto failed; } /* Pre-initialize implicitly using argv: make sure that -X dev is used to configure the allocation in preinitialization */ wchar_t *argv[] = {L"python3", L"-X", L"dev", L"script.py"}; - err = _PyCoreConfig_SetWideArgv(&config, Py_ARRAY_LENGTH(argv), argv); - if (_PyInitError_Failed(err)) { + status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv); + if (PyStatus_Exception(status)) { goto failed; } - err = _PyCoreConfig_SetString(&config, &config.program_name, + status = PyConfig_SetString(&config, &config.program_name, L"./_testembed"); - if (_PyInitError_Failed(err)) { + if (PyStatus_Exception(status)) { goto failed; } - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { goto failed; } - _PyCoreConfig_Clear(&config); + PyConfig_Clear(&config); dump_config(); Py_Finalize(); return 0; failed: - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + PyConfig_Clear(&config); + Py_ExitStatusException(status); } @@ -923,8 +923,8 @@ static void set_all_global_config_variables(void) static int check_preinit_isolated_config(int preinit) { - _PyInitError err; - _PyPreConfig *rt_preconfig; + PyStatus status; + PyPreConfig *rt_preconfig; /* environment variables must be ignored */ set_all_env_vars(); @@ -933,12 +933,12 @@ static int check_preinit_isolated_config(int preinit) set_all_global_config_variables(); if (preinit) { - _PyPreConfig preconfig; - _PyPreConfig_InitIsolatedConfig(&preconfig); + PyPreConfig preconfig; + PyPreConfig_InitIsolatedConfig(&preconfig); - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } rt_preconfig = &_PyRuntime.preconfig; @@ -946,18 +946,18 @@ static int check_preinit_isolated_config(int preinit) assert(rt_preconfig->use_environment == 0); } - _PyCoreConfig config; - err = _PyCoreConfig_InitIsolatedConfig(&config); - if (_PyInitError_Failed(err)) { - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + PyConfig config; + status = PyConfig_InitIsolatedConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); } config.program_name = L"./_testembed"; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); } rt_preconfig = &_PyRuntime.preconfig; @@ -984,7 +984,7 @@ static int test_init_isolated_config(void) static int check_init_python_config(int preinit) { - _PyInitError err; + PyStatus status; /* global configuration variables must be ignored */ set_all_global_config_variables(); @@ -1000,25 +1000,25 @@ static int check_init_python_config(int preinit) #endif if (preinit) { - _PyPreConfig preconfig; - _PyPreConfig_InitPythonConfig(&preconfig); + PyPreConfig preconfig; + PyPreConfig_InitPythonConfig(&preconfig); - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } } - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } config.program_name = L"./_testembed"; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -1040,28 +1040,28 @@ static int test_init_python_config(void) static int test_init_dont_configure_locale(void) { - _PyInitError err; + PyStatus status; - _PyPreConfig preconfig; - _PyPreConfig_InitPythonConfig(&preconfig); + PyPreConfig preconfig; + PyPreConfig_InitPythonConfig(&preconfig); preconfig.configure_locale = 0; preconfig.coerce_c_locale = 1; preconfig.coerce_c_locale_warn = 1; - err = _Py_PreInitialize(&preconfig); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } config.program_name = L"./_testembed"; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); @@ -1072,19 +1072,19 @@ static int test_init_dont_configure_locale(void) static int test_init_dev_mode(void) { - _PyInitError err; - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyStatus status; + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } putenv("PYTHONFAULTHANDLER="); putenv("PYTHONMALLOC="); config.dev_mode = 1; config.program_name = L"./_testembed"; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } dump_config(); Py_Finalize(); @@ -1250,39 +1250,39 @@ static int test_audit_subinterpreter(void) static int test_init_read_set(void) { - _PyInitError err; - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyStatus status; + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - err = _PyCoreConfig_DecodeLocale(&config, &config.program_name, + status = PyConfig_SetBytesString(&config, &config.program_name, "./init_read_set"); - if (_PyInitError_Failed(err)) { + if (PyStatus_Exception(status)) { goto fail; } - err = _PyCoreConfig_Read(&config); - if (_PyInitError_Failed(err)) { + status = PyConfig_Read(&config); + if (PyStatus_Exception(status)) { goto fail; } - if (_PyWstrList_Append(&config.module_search_paths, - L"init_read_set_path") < 0) { - err = _PyInitError_NoMemory(); + status = PyWideStringList_Append(&config.module_search_paths, + L"init_read_set_path"); + if (PyStatus_Exception(status)) { goto fail; } - /* override executable computed by _PyCoreConfig_Read() */ - err = _PyCoreConfig_SetString(&config, &config.executable, L"my_executable"); - if (_PyInitError_Failed(err)) { + /* override executable computed by PyConfig_Read() */ + status = PyConfig_SetString(&config, &config.executable, L"my_executable"); + if (PyStatus_Exception(status)) { goto fail; } - err = _Py_InitializeFromConfig(&config); - _PyCoreConfig_Clear(&config); - if (_PyInitError_Failed(err)) { + status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status)) { goto fail; } dump_config(); @@ -1290,7 +1290,7 @@ static int test_init_read_set(void) return 0; fail: - _Py_ExitInitError(err); + Py_ExitStatusException(status); } @@ -1301,7 +1301,7 @@ wchar_t *init_main_argv[] = { L"arg2"}; -static void configure_init_main(_PyCoreConfig *config) +static void configure_init_main(PyConfig *config) { config->argv.length = Py_ARRAY_LENGTH(init_main_argv); config->argv.items = init_main_argv; @@ -1312,38 +1312,38 @@ static void configure_init_main(_PyCoreConfig *config) static int test_init_run_main(void) { - _PyInitError err; - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyStatus status; + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } configure_init_main(&config); - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - return _Py_RunMain(); + return Py_RunMain(); } static int test_init_main(void) { - _PyInitError err; - _PyCoreConfig config; + PyStatus status; + PyConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } configure_init_main(&config); config._init_main = 0; - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */ @@ -1355,51 +1355,51 @@ static int test_init_main(void) exit(1); } - err = _Py_InitializeMain(); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = _Py_InitializeMain(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } - return _Py_RunMain(); + return Py_RunMain(); } static int test_run_main(void) { - _PyInitError err; - _PyCoreConfig config; + PyStatus status; + PyConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { goto failed; } wchar_t *argv[] = {L"python3", L"-c", (L"import sys; " - L"print(f'_Py_RunMain(): sys.argv={sys.argv}')"), + L"print(f'Py_RunMain(): sys.argv={sys.argv}')"), L"arg2"}; - err = _PyCoreConfig_SetWideArgv(&config, Py_ARRAY_LENGTH(argv), argv); - if (_PyInitError_Failed(err)) { + status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv); + if (PyStatus_Exception(status)) { goto failed; } - err = _PyCoreConfig_SetString(&config, &config.program_name, + status = PyConfig_SetString(&config, &config.program_name, L"./python3"); - if (_PyInitError_Failed(err)) { + if (PyStatus_Exception(status)) { goto failed; } - err = _Py_InitializeFromConfig(&config); - if (_PyInitError_Failed(err)) { + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { goto failed; } - _PyCoreConfig_Clear(&config); + PyConfig_Clear(&config); - return _Py_RunMain(); + return Py_RunMain(); failed: - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + PyConfig_Clear(&config); + Py_ExitStatusException(status); } diff --git a/Programs/python.c b/Programs/python.c index 4c12d38c..1cc3c42 100644 --- a/Programs/python.c +++ b/Programs/python.c @@ -13,6 +13,6 @@ wmain(int argc, wchar_t **argv) int main(int argc, char **argv) { - return _Py_UnixMain(argc, argv); + return Py_BytesMain(argc, argv); } #endif diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ff5a512..5d58085 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2824,7 +2824,7 @@ _PyBuiltin_Init(void) { PyObject *mod, *dict, *debug; - const _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + const PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (PyType_Ready(&PyFilter_Type) < 0 || PyType_Ready(&PyMap_Type) < 0 || diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index fe71cc3..43f5264 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -1,5 +1,5 @@ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #ifdef MS_WINDOWS # include /* All sample MSDN wincrypt programs include the header below. It is at least @@ -547,14 +547,14 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size) } -_PyInitError -_Py_HashRandomization_Init(const _PyCoreConfig *config) +PyStatus +_Py_HashRandomization_Init(const PyConfig *config) { void *secret = &_Py_HashSecret; Py_ssize_t secret_size = sizeof(_Py_HashSecret_t); if (_Py_HashSecret_Initialized) { - return _Py_INIT_OK(); + return _PyStatus_OK(); } _Py_HashSecret_Initialized = 1; @@ -579,11 +579,11 @@ _Py_HashRandomization_Init(const _PyCoreConfig *config) pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */ res = pyurandom(secret, secret_size, 0, 0); if (res < 0) { - return _Py_INIT_ERR("failed to get random numbers " + return _PyStatus_ERR("failed to get random numbers " "to initialize Python"); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } diff --git a/Python/compile.c b/Python/compile.c index 734e840..425d0d6 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -311,7 +311,7 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, PyCodeObject *co = NULL; PyCompilerFlags local_flags; int merged; - _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (!__doc__) { __doc__ = PyUnicode_InternFromString("__doc__"); @@ -4782,7 +4782,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) return compiler_error(c, "'await' outside function"); } - if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION && + if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION && c->u->u_scope_type != COMPILER_SCOPE_COMPREHENSION){ return compiler_error(c, "'await' outside async function"); } diff --git a/Python/coreconfig.c b/Python/coreconfig.c deleted file mode 100644 index 89ccff4..0000000 --- a/Python/coreconfig.c +++ /dev/null @@ -1,2429 +0,0 @@ -#include "Python.h" -#include "osdefs.h" /* DELIM */ -#include "pycore_coreconfig.h" -#include "pycore_fileutils.h" -#include "pycore_getopt.h" -#include "pycore_pylifecycle.h" -#include "pycore_pymem.h" -#include "pycore_pystate.h" /* _PyRuntime */ -#include "pycore_pathconfig.h" -#include /* setlocale() */ -#ifdef HAVE_LANGINFO_H -# include /* nl_langinfo(CODESET) */ -#endif -#if defined(MS_WINDOWS) || defined(__CYGWIN__) -# include /* GetACP() */ -# ifdef HAVE_IO_H -# include -# endif -# ifdef HAVE_FCNTL_H -# include /* O_BINARY */ -# endif -#endif - - -/* --- Command line options --------------------------------------- */ - -/* Short usage message (with %s for argv0) */ -static const char usage_line[] = -"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n"; - -/* Long usage message, split into parts < 512 bytes */ -static const char usage_1[] = "\ -Options and arguments (and corresponding environment variables):\n\ --b : issue warnings about str(bytes_instance), str(bytearray_instance)\n\ - and comparing bytes/bytearray with str. (-bb: issue errors)\n\ --B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\ --c cmd : program passed in as string (terminates option list)\n\ --d : debug output from parser; also PYTHONDEBUG=x\n\ --E : ignore PYTHON* environment variables (such as PYTHONPATH)\n\ --h : print this help message and exit (also --help)\n\ -"; -static const char usage_2[] = "\ --i : inspect interactively after running script; forces a prompt even\n\ - if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\ --I : isolate Python from the user's environment (implies -E and -s)\n\ --m mod : run library module as a script (terminates option list)\n\ --O : remove assert and __debug__-dependent statements; add .opt-1 before\n\ - .pyc extension; also PYTHONOPTIMIZE=x\n\ --OO : do -O changes and also discard docstrings; add .opt-2 before\n\ - .pyc extension\n\ --q : don't print version and copyright messages on interactive startup\n\ --s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ --S : don't imply 'import site' on initialization\n\ -"; -static const char usage_3[] = "\ --u : force the stdout and stderr streams to be unbuffered;\n\ - this option has no effect on stdin; also PYTHONUNBUFFERED=x\n\ --v : verbose (trace import statements); also PYTHONVERBOSE=x\n\ - can be supplied multiple times to increase verbosity\n\ --V : print the Python version number and exit (also --version)\n\ - when given twice, print more information about the build\n\ --W arg : warning control; arg is action:message:category:module:lineno\n\ - also PYTHONWARNINGS=arg\n\ --x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\ --X opt : set implementation-specific option\n\ ---check-hash-based-pycs always|default|never:\n\ - control how Python invalidates hash-based .pyc files\n\ -"; -static const char usage_4[] = "\ -file : program read from script file\n\ -- : program read from stdin (default; interactive mode if a tty)\n\ -arg ...: arguments passed to program in sys.argv[1:]\n\n\ -Other environment variables:\n\ -PYTHONSTARTUP: file executed on interactive startup (no default)\n\ -PYTHONPATH : '%lc'-separated list of directories prefixed to the\n\ - default module search path. The result is sys.path.\n\ -"; -static const char usage_5[] = -"PYTHONHOME : alternate directory (or %lc).\n" -" The default module search path uses %s.\n" -"PYTHONCASEOK : ignore case in 'import' statements (Windows).\n" -"PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n" -"PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n"; -static const char usage_6[] = -"PYTHONHASHSEED: if this variable is set to 'random', a random value is used\n" -" to seed the hashes of str, bytes and datetime objects. It can also be\n" -" set to an integer in the range [0,4294967295] to get hash values with a\n" -" predictable seed.\n" -"PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n" -" on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n" -" hooks.\n" -"PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n" -" coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of\n" -" locale coercion and locale compatibility warnings on stderr.\n" -"PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n" -" debugger. It can be set to the callable of your debugger of choice.\n" -"PYTHONDEVMODE: enable the development mode.\n" -"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n"; - -#if defined(MS_WINDOWS) -# define PYTHONHOMEHELP "\\python{major}{minor}" -#else -# define PYTHONHOMEHELP "/lib/pythonX.X" -#endif - - -/* --- Global configuration variables ----------------------------- */ - -/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change - stdin and stdout error handler to "surrogateescape". */ -int Py_UTF8Mode = 0; -int Py_DebugFlag = 0; /* Needed by parser.c */ -int Py_VerboseFlag = 0; /* Needed by import.c */ -int Py_QuietFlag = 0; /* Needed by sysmodule.c */ -int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */ -int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */ -int Py_OptimizeFlag = 0; /* Needed by compile.c */ -int Py_NoSiteFlag = 0; /* Suppress 'import site' */ -int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */ -int Py_FrozenFlag = 0; /* Needed by getpath.c */ -int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */ -int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */ -int Py_NoUserSiteDirectory = 0; /* for -s and site.py */ -int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */ -int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */ -int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */ -#ifdef MS_WINDOWS -int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */ -int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */ -#endif - - -static PyObject * -_Py_GetGlobalVariablesAsDict(void) -{ - PyObject *dict, *obj; - - dict = PyDict_New(); - if (dict == NULL) { - return NULL; - } - -#define SET_ITEM(KEY, EXPR) \ - do { \ - obj = (EXPR); \ - if (obj == NULL) { \ - return NULL; \ - } \ - int res = PyDict_SetItemString(dict, (KEY), obj); \ - Py_DECREF(obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) -#define SET_ITEM_INT(VAR) \ - SET_ITEM(#VAR, PyLong_FromLong(VAR)) -#define FROM_STRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromString(STR) \ - : (Py_INCREF(Py_None), Py_None)) -#define SET_ITEM_STR(VAR) \ - SET_ITEM(#VAR, FROM_STRING(VAR)) - - SET_ITEM_STR(Py_FileSystemDefaultEncoding); - SET_ITEM_INT(Py_HasFileSystemDefaultEncoding); - SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors); - SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors); - - SET_ITEM_INT(Py_UTF8Mode); - SET_ITEM_INT(Py_DebugFlag); - SET_ITEM_INT(Py_VerboseFlag); - SET_ITEM_INT(Py_QuietFlag); - SET_ITEM_INT(Py_InteractiveFlag); - SET_ITEM_INT(Py_InspectFlag); - - SET_ITEM_INT(Py_OptimizeFlag); - SET_ITEM_INT(Py_NoSiteFlag); - SET_ITEM_INT(Py_BytesWarningFlag); - SET_ITEM_INT(Py_FrozenFlag); - SET_ITEM_INT(Py_IgnoreEnvironmentFlag); - SET_ITEM_INT(Py_DontWriteBytecodeFlag); - SET_ITEM_INT(Py_NoUserSiteDirectory); - SET_ITEM_INT(Py_UnbufferedStdioFlag); - SET_ITEM_INT(Py_HashRandomizationFlag); - SET_ITEM_INT(Py_IsolatedFlag); - -#ifdef MS_WINDOWS - SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag); - SET_ITEM_INT(Py_LegacyWindowsStdioFlag); -#endif - - return dict; - -fail: - Py_DECREF(dict); - return NULL; - -#undef FROM_STRING -#undef SET_ITEM -#undef SET_ITEM_INT -#undef SET_ITEM_STR -} - - -/* --- _PyInitError ----------------------------------------------- */ - -_PyInitError _PyInitError_Ok(void) -{ return _Py_INIT_OK(); } - -_PyInitError _PyInitError_Error(const char *err_msg) -{ - return (_PyInitError){._type = _Py_INIT_ERR_TYPE_ERROR, - .err_msg = err_msg}; -} - -_PyInitError _PyInitError_NoMemory(void) -{ return _PyInitError_Error("memory allocation failed"); } - -_PyInitError _PyInitError_Exit(int exitcode) -{ return _Py_INIT_EXIT(exitcode); } - - -int _PyInitError_IsError(_PyInitError err) -{ return _Py_INIT_IS_ERROR(err); } - -int _PyInitError_IsExit(_PyInitError err) -{ return _Py_INIT_IS_EXIT(err); } - -int _PyInitError_Failed(_PyInitError err) -{ return _Py_INIT_FAILED(err); } - - -/* --- _PyWstrList ------------------------------------------------ */ - -#ifndef NDEBUG -int -_PyWstrList_CheckConsistency(const _PyWstrList *list) -{ - assert(list->length >= 0); - if (list->length != 0) { - assert(list->items != NULL); - } - for (Py_ssize_t i = 0; i < list->length; i++) { - assert(list->items[i] != NULL); - } - return 1; -} -#endif /* Py_DEBUG */ - - -void -_PyWstrList_Clear(_PyWstrList *list) -{ - assert(_PyWstrList_CheckConsistency(list)); - for (Py_ssize_t i=0; i < list->length; i++) { - PyMem_RawFree(list->items[i]); - } - PyMem_RawFree(list->items); - list->length = 0; - list->items = NULL; -} - - -int -_PyWstrList_Copy(_PyWstrList *list, const _PyWstrList *list2) -{ - assert(_PyWstrList_CheckConsistency(list)); - assert(_PyWstrList_CheckConsistency(list2)); - - if (list2->length == 0) { - _PyWstrList_Clear(list); - return 0; - } - - _PyWstrList copy = _PyWstrList_INIT; - - size_t size = list2->length * sizeof(list2->items[0]); - copy.items = PyMem_RawMalloc(size); - if (copy.items == NULL) { - return -1; - } - - for (Py_ssize_t i=0; i < list2->length; i++) { - wchar_t *item = _PyMem_RawWcsdup(list2->items[i]); - if (item == NULL) { - _PyWstrList_Clear(©); - return -1; - } - copy.items[i] = item; - copy.length = i + 1; - } - - _PyWstrList_Clear(list); - *list = copy; - return 0; -} - - -int -_PyWstrList_Append(_PyWstrList *list, const wchar_t *item) -{ - if (list->length == PY_SSIZE_T_MAX) { - /* lenght+1 would overflow */ - return -1; - } - - wchar_t *item2 = _PyMem_RawWcsdup(item); - if (item2 == NULL) { - return -1; - } - - size_t size = (list->length + 1) * sizeof(list->items[0]); - wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size); - if (items2 == NULL) { - PyMem_RawFree(item2); - return -1; - } - - items2[list->length] = item2; - list->items = items2; - list->length++; - return 0; -} - - -int -_PyWstrList_Extend(_PyWstrList *list, const _PyWstrList *list2) -{ - for (Py_ssize_t i = 0; i < list2->length; i++) { - if (_PyWstrList_Append(list, list2->items[i])) { - return -1; - } - } - return 0; -} - - -static int -_PyWstrList_Find(_PyWstrList *list, const wchar_t *item) -{ - for (Py_ssize_t i = 0; i < list->length; i++) { - if (wcscmp(list->items[i], item) == 0) { - return 1; - } - } - return 0; -} - - -PyObject* -_PyWstrList_AsList(const _PyWstrList *list) -{ - assert(_PyWstrList_CheckConsistency(list)); - - PyObject *pylist = PyList_New(list->length); - if (pylist == NULL) { - return NULL; - } - - for (Py_ssize_t i = 0; i < list->length; i++) { - PyObject *item = PyUnicode_FromWideChar(list->items[i], -1); - if (item == NULL) { - Py_DECREF(pylist); - return NULL; - } - PyList_SET_ITEM(pylist, i, item); - } - return pylist; -} - - -/* --- Py_SetStandardStreamEncoding() ----------------------------- */ - -/* Helper to allow an embedding application to override the normal - * mechanism that attempts to figure out an appropriate IO encoding - */ - -static char *_Py_StandardStreamEncoding = NULL; -static char *_Py_StandardStreamErrors = NULL; - -int -Py_SetStandardStreamEncoding(const char *encoding, const char *errors) -{ - if (Py_IsInitialized()) { - /* This is too late to have any effect */ - return -1; - } - - int res = 0; - - /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(), - but Py_Initialize() can change the allocator. Use a known allocator - to be able to release the memory later. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - /* Can't call PyErr_NoMemory() on errors, as Python hasn't been - * initialised yet. - * - * However, the raw memory allocators are initialised appropriately - * as C static variables, so _PyMem_RawStrdup is OK even though - * Py_Initialize hasn't been called yet. - */ - if (encoding) { - PyMem_RawFree(_Py_StandardStreamEncoding); - _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); - if (!_Py_StandardStreamEncoding) { - res = -2; - goto done; - } - } - if (errors) { - PyMem_RawFree(_Py_StandardStreamErrors); - _Py_StandardStreamErrors = _PyMem_RawStrdup(errors); - if (!_Py_StandardStreamErrors) { - PyMem_RawFree(_Py_StandardStreamEncoding); - _Py_StandardStreamEncoding = NULL; - res = -3; - goto done; - } - } -#ifdef MS_WINDOWS - if (_Py_StandardStreamEncoding) { - /* Overriding the stream encoding implies legacy streams */ - Py_LegacyWindowsStdioFlag = 1; - } -#endif - -done: - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - return res; -} - - -void -_Py_ClearStandardStreamEncoding(void) -{ - /* Use the same allocator than Py_SetStandardStreamEncoding() */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - /* We won't need them anymore. */ - if (_Py_StandardStreamEncoding) { - PyMem_RawFree(_Py_StandardStreamEncoding); - _Py_StandardStreamEncoding = NULL; - } - if (_Py_StandardStreamErrors) { - PyMem_RawFree(_Py_StandardStreamErrors); - _Py_StandardStreamErrors = NULL; - } - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -} - - -/* --- Py_GetArgcArgv() ------------------------------------------- */ - -/* For Py_GetArgcArgv(); set by _Py_SetArgcArgv() */ -static _PyWstrList orig_argv = {.length = 0, .items = NULL}; - - -void -_Py_ClearArgcArgv(void) -{ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - _PyWstrList_Clear(&orig_argv); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -} - - -static int -_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv) -{ - const _PyWstrList argv_list = {.length = argc, .items = (wchar_t **)argv}; - int res; - - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - res = _PyWstrList_Copy(&orig_argv, &argv_list); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return res; -} - - -/* Make the *original* argc/argv available to other modules. - This is rare, but it is needed by the secureware extension. */ -void -Py_GetArgcArgv(int *argc, wchar_t ***argv) -{ - *argc = (int)orig_argv.length; - *argv = orig_argv.items; -} - - -/* --- _PyCoreConfig ---------------------------------------------- */ - -#define DECODE_LOCALE_ERR(NAME, LEN) \ - (((LEN) == -2) \ - ? _Py_INIT_ERR("cannot decode " NAME) \ - : _Py_INIT_NO_MEMORY()) - -/* Free memory allocated in config, but don't clear all attributes */ -void -_PyCoreConfig_Clear(_PyCoreConfig *config) -{ -#define CLEAR(ATTR) \ - do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ - } while (0) - - CLEAR(config->pycache_prefix); - CLEAR(config->module_search_path_env); - CLEAR(config->home); - CLEAR(config->program_name); - - _PyWstrList_Clear(&config->argv); - _PyWstrList_Clear(&config->warnoptions); - _PyWstrList_Clear(&config->xoptions); - _PyWstrList_Clear(&config->module_search_paths); - config->use_module_search_paths = 0; - - CLEAR(config->executable); - CLEAR(config->prefix); - CLEAR(config->base_prefix); - CLEAR(config->exec_prefix); - CLEAR(config->base_exec_prefix); - - CLEAR(config->filesystem_encoding); - CLEAR(config->filesystem_errors); - CLEAR(config->stdio_encoding); - CLEAR(config->stdio_errors); - CLEAR(config->run_command); - CLEAR(config->run_module); - CLEAR(config->run_filename); - CLEAR(config->check_hash_pycs_mode); -#undef CLEAR -} - - -void -_PyCoreConfig_InitCompatConfig(_PyCoreConfig *config) -{ - memset(config, 0, sizeof(*config)); - - config->_config_version = _Py_CONFIG_VERSION; - config->_config_init = (int)_PyConfig_INIT_COMPAT; - config->isolated = -1; - config->use_environment = -1; - config->dev_mode = -1; - config->install_signal_handlers = 1; - config->use_hash_seed = -1; - config->faulthandler = -1; - config->tracemalloc = -1; - config->use_module_search_paths = 0; - config->parse_argv = 0; - config->site_import = -1; - config->bytes_warning = -1; - config->inspect = -1; - config->interactive = -1; - config->optimization_level = -1; - config->parser_debug= -1; - config->write_bytecode = -1; - config->verbose = -1; - config->quiet = -1; - config->user_site_directory = -1; - config->configure_c_stdio = 0; - config->buffered_stdio = -1; - config->_install_importlib = 1; - config->check_hash_pycs_mode = NULL; - config->pathconfig_warnings = -1; - config->_init_main = 1; -#ifdef MS_WINDOWS - config->legacy_windows_stdio = -1; -#endif -} - - -static void -_PyCoreConfig_InitDefaults(_PyCoreConfig *config) -{ - _PyCoreConfig_InitCompatConfig(config); - - config->isolated = 0; - config->use_environment = 1; - config->site_import = 1; - config->bytes_warning = 0; - config->inspect = 0; - config->interactive = 0; - config->optimization_level = 0; - config->parser_debug= 0; - config->write_bytecode = 1; - config->verbose = 0; - config->quiet = 0; - config->user_site_directory = 1; - config->buffered_stdio = 1; - config->pathconfig_warnings = 1; -#ifdef MS_WINDOWS - config->legacy_windows_stdio = 0; -#endif -} - - -_PyInitError -_PyCoreConfig_InitPythonConfig(_PyCoreConfig *config) -{ - _PyCoreConfig_InitDefaults(config); - - config->_config_init = (int)_PyConfig_INIT_PYTHON; - config->configure_c_stdio = 1; - config->parse_argv = 1; - - return _Py_INIT_OK(); -} - - -_PyInitError -_PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config) -{ - _PyCoreConfig_InitDefaults(config); - - config->_config_init = (int)_PyConfig_INIT_ISOLATED; - config->isolated = 1; - config->use_environment = 0; - config->user_site_directory = 0; - config->dev_mode = 0; - config->install_signal_handlers = 0; - config->use_hash_seed = 0; - config->faulthandler = 0; - config->tracemalloc = 0; - config->pathconfig_warnings = 0; -#ifdef MS_WINDOWS - config->legacy_windows_stdio = 0; -#endif - - return _Py_INIT_OK(); -} - - -/* Copy str into *config_str (duplicate the string) */ -_PyInitError -_PyCoreConfig_SetString(_PyCoreConfig *config, wchar_t **config_str, - const wchar_t *str) -{ - _PyInitError err = _Py_PreInitializeFromCoreConfig(config, NULL); - if (_Py_INIT_FAILED(err)) { - return err; - } - - wchar_t *str2; - if (str != NULL) { - str2 = _PyMem_RawWcsdup(str); - if (str2 == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - else { - str2 = NULL; - } - PyMem_RawFree(*config_str); - *config_str = str2; - return _Py_INIT_OK(); -} - - -static _PyInitError -_PyCoreConfig_DecodeLocaleErr(_PyCoreConfig *config, wchar_t **config_str, - const char *str, const char *decode_err_msg) -{ - _PyInitError err = _Py_PreInitializeFromCoreConfig(config, NULL); - if (_Py_INIT_FAILED(err)) { - return err; - } - - wchar_t *str2; - if (str != NULL) { - size_t len; - str2 = Py_DecodeLocale(str, &len); - if (str2 == NULL) { - if (len == (size_t)-2) { - return _Py_INIT_ERR(decode_err_msg); - } - else { - return _Py_INIT_NO_MEMORY(); - } - } - } - else { - str2 = NULL; - } - PyMem_RawFree(*config_str); - *config_str = str2; - return _Py_INIT_OK(); -} - - -#define CONFIG_DECODE_LOCALE(config, config_str, str, NAME) \ - _PyCoreConfig_DecodeLocaleErr(config, config_str, str, "cannot decode " NAME) - - -/* Decode str using Py_DecodeLocale() and set the result into *config_str. - Pre-initialize Python if needed to ensure that encodings are properly - configured. */ -_PyInitError -_PyCoreConfig_DecodeLocale(_PyCoreConfig *config, wchar_t **config_str, - const char *str) -{ - return CONFIG_DECODE_LOCALE(config, config_str, str, "string"); -} - - -_PyInitError -_PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) -{ - _PyInitError err; - _PyCoreConfig_Clear(config); - -#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR -#define COPY_WSTR_ATTR(ATTR) \ - do { \ - err = _PyCoreConfig_SetString(config, &config->ATTR, config2->ATTR); \ - if (_Py_INIT_FAILED(err)) { \ - return err; \ - } \ - } while (0) -#define COPY_WSTRLIST(LIST) \ - do { \ - if (_PyWstrList_Copy(&config->LIST, &config2->LIST) < 0 ) { \ - return _Py_INIT_NO_MEMORY(); \ - } \ - } while (0) - - COPY_ATTR(_config_init); - COPY_ATTR(isolated); - COPY_ATTR(use_environment); - COPY_ATTR(dev_mode); - COPY_ATTR(install_signal_handlers); - COPY_ATTR(use_hash_seed); - COPY_ATTR(hash_seed); - COPY_ATTR(_install_importlib); - COPY_ATTR(faulthandler); - COPY_ATTR(tracemalloc); - COPY_ATTR(import_time); - COPY_ATTR(show_ref_count); - COPY_ATTR(show_alloc_count); - COPY_ATTR(dump_refs); - COPY_ATTR(malloc_stats); - - COPY_WSTR_ATTR(pycache_prefix); - COPY_WSTR_ATTR(module_search_path_env); - COPY_WSTR_ATTR(home); - COPY_WSTR_ATTR(program_name); - - COPY_ATTR(parse_argv); - COPY_WSTRLIST(argv); - COPY_WSTRLIST(warnoptions); - COPY_WSTRLIST(xoptions); - COPY_WSTRLIST(module_search_paths); - COPY_ATTR(use_module_search_paths); - - COPY_WSTR_ATTR(executable); - COPY_WSTR_ATTR(prefix); - COPY_WSTR_ATTR(base_prefix); - COPY_WSTR_ATTR(exec_prefix); - COPY_WSTR_ATTR(base_exec_prefix); - - COPY_ATTR(site_import); - COPY_ATTR(bytes_warning); - COPY_ATTR(inspect); - COPY_ATTR(interactive); - COPY_ATTR(optimization_level); - COPY_ATTR(parser_debug); - COPY_ATTR(write_bytecode); - COPY_ATTR(verbose); - COPY_ATTR(quiet); - COPY_ATTR(user_site_directory); - COPY_ATTR(configure_c_stdio); - COPY_ATTR(buffered_stdio); - COPY_WSTR_ATTR(filesystem_encoding); - COPY_WSTR_ATTR(filesystem_errors); - COPY_WSTR_ATTR(stdio_encoding); - COPY_WSTR_ATTR(stdio_errors); -#ifdef MS_WINDOWS - COPY_ATTR(legacy_windows_stdio); -#endif - COPY_ATTR(skip_source_first_line); - COPY_WSTR_ATTR(run_command); - COPY_WSTR_ATTR(run_module); - COPY_WSTR_ATTR(run_filename); - COPY_WSTR_ATTR(check_hash_pycs_mode); - COPY_ATTR(pathconfig_warnings); - COPY_ATTR(_init_main); - -#undef COPY_ATTR -#undef COPY_WSTR_ATTR -#undef COPY_WSTRLIST - return _Py_INIT_OK(); -} - - -static PyObject * -_PyCoreConfig_AsDict(const _PyCoreConfig *config) -{ - PyObject *dict; - - dict = PyDict_New(); - if (dict == NULL) { - return NULL; - } - -#define SET_ITEM(KEY, EXPR) \ - do { \ - PyObject *obj = (EXPR); \ - if (obj == NULL) { \ - goto fail; \ - } \ - int res = PyDict_SetItemString(dict, (KEY), obj); \ - Py_DECREF(obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) -#define SET_ITEM_INT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) -#define SET_ITEM_UINT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR)) -#define FROM_WSTRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromWideChar(STR, -1) \ - : (Py_INCREF(Py_None), Py_None)) -#define SET_ITEM_WSTR(ATTR) \ - SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR)) -#define SET_ITEM_WSTRLIST(LIST) \ - SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST)) - - SET_ITEM_INT(_config_init); - SET_ITEM_INT(isolated); - SET_ITEM_INT(use_environment); - SET_ITEM_INT(dev_mode); - SET_ITEM_INT(install_signal_handlers); - SET_ITEM_INT(use_hash_seed); - SET_ITEM_UINT(hash_seed); - SET_ITEM_INT(faulthandler); - SET_ITEM_INT(tracemalloc); - SET_ITEM_INT(import_time); - SET_ITEM_INT(show_ref_count); - SET_ITEM_INT(show_alloc_count); - SET_ITEM_INT(dump_refs); - SET_ITEM_INT(malloc_stats); - SET_ITEM_WSTR(filesystem_encoding); - SET_ITEM_WSTR(filesystem_errors); - SET_ITEM_WSTR(pycache_prefix); - SET_ITEM_WSTR(program_name); - SET_ITEM_INT(parse_argv); - SET_ITEM_WSTRLIST(argv); - SET_ITEM_WSTRLIST(xoptions); - SET_ITEM_WSTRLIST(warnoptions); - SET_ITEM_WSTR(module_search_path_env); - SET_ITEM_WSTR(home); - SET_ITEM_WSTRLIST(module_search_paths); - SET_ITEM_WSTR(executable); - SET_ITEM_WSTR(prefix); - SET_ITEM_WSTR(base_prefix); - SET_ITEM_WSTR(exec_prefix); - SET_ITEM_WSTR(base_exec_prefix); - SET_ITEM_INT(site_import); - SET_ITEM_INT(bytes_warning); - SET_ITEM_INT(inspect); - SET_ITEM_INT(interactive); - SET_ITEM_INT(optimization_level); - SET_ITEM_INT(parser_debug); - SET_ITEM_INT(write_bytecode); - SET_ITEM_INT(verbose); - SET_ITEM_INT(quiet); - SET_ITEM_INT(user_site_directory); - SET_ITEM_INT(configure_c_stdio); - SET_ITEM_INT(buffered_stdio); - SET_ITEM_WSTR(stdio_encoding); - SET_ITEM_WSTR(stdio_errors); -#ifdef MS_WINDOWS - SET_ITEM_INT(legacy_windows_stdio); -#endif - SET_ITEM_INT(skip_source_first_line); - SET_ITEM_WSTR(run_command); - SET_ITEM_WSTR(run_module); - SET_ITEM_WSTR(run_filename); - SET_ITEM_INT(_install_importlib); - SET_ITEM_WSTR(check_hash_pycs_mode); - SET_ITEM_INT(pathconfig_warnings); - SET_ITEM_INT(_init_main); - - return dict; - -fail: - Py_DECREF(dict); - return NULL; - -#undef FROM_WSTRING -#undef SET_ITEM -#undef SET_ITEM_INT -#undef SET_ITEM_UINT -#undef SET_ITEM_WSTR -#undef SET_ITEM_WSTRLIST -} - - -static const char* -_PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) -{ - return _Py_GetEnv(config->use_environment, name); -} - - -/* Get a copy of the environment variable as wchar_t*. - Return 0 on success, but *dest can be NULL. - Return -1 on memory allocation failure. Return -2 on decoding error. */ -static _PyInitError -_PyCoreConfig_GetEnvDup(_PyCoreConfig *config, - wchar_t **dest, - wchar_t *wname, char *name, - const char *decode_err_msg) -{ - assert(*dest == NULL); - assert(config->use_environment >= 0); - - if (!config->use_environment) { - *dest = NULL; - return _Py_INIT_OK(); - } - -#ifdef MS_WINDOWS - const wchar_t *var = _wgetenv(wname); - if (!var || var[0] == '\0') { - *dest = NULL; - return _Py_INIT_OK(); - } - - return _PyCoreConfig_SetString(config, dest, var); -#else - const char *var = getenv(name); - if (!var || var[0] == '\0') { - *dest = NULL; - return _Py_INIT_OK(); - } - - return _PyCoreConfig_DecodeLocaleErr(config, dest, var, decode_err_msg); -#endif -} - - -#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \ - _PyCoreConfig_GetEnvDup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME) - - -static void -_PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) -{ - if (config->_config_init != _PyConfig_INIT_COMPAT) { - /* Python and Isolated configuration ignore global variables */ - return; - } - -#define COPY_FLAG(ATTR, VALUE) \ - if (config->ATTR == -1) { \ - config->ATTR = VALUE; \ - } -#define COPY_NOT_FLAG(ATTR, VALUE) \ - if (config->ATTR == -1) { \ - config->ATTR = !(VALUE); \ - } - - COPY_FLAG(isolated, Py_IsolatedFlag); - COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); - COPY_FLAG(bytes_warning, Py_BytesWarningFlag); - COPY_FLAG(inspect, Py_InspectFlag); - COPY_FLAG(interactive, Py_InteractiveFlag); - COPY_FLAG(optimization_level, Py_OptimizeFlag); - COPY_FLAG(parser_debug, Py_DebugFlag); - COPY_FLAG(verbose, Py_VerboseFlag); - COPY_FLAG(quiet, Py_QuietFlag); -#ifdef MS_WINDOWS - COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag); -#endif - COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag); - - COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag); - COPY_NOT_FLAG(site_import, Py_NoSiteFlag); - COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag); - COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory); - -#undef COPY_FLAG -#undef COPY_NOT_FLAG -} - - -/* Set Py_xxx global configuration variables from 'config' configuration. */ -static void -_PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) -{ -#define COPY_FLAG(ATTR, VAR) \ - if (config->ATTR != -1) { \ - VAR = config->ATTR; \ - } -#define COPY_NOT_FLAG(ATTR, VAR) \ - if (config->ATTR != -1) { \ - VAR = !config->ATTR; \ - } - - COPY_FLAG(isolated, Py_IsolatedFlag); - COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); - COPY_FLAG(bytes_warning, Py_BytesWarningFlag); - COPY_FLAG(inspect, Py_InspectFlag); - COPY_FLAG(interactive, Py_InteractiveFlag); - COPY_FLAG(optimization_level, Py_OptimizeFlag); - COPY_FLAG(parser_debug, Py_DebugFlag); - COPY_FLAG(verbose, Py_VerboseFlag); - COPY_FLAG(quiet, Py_QuietFlag); -#ifdef MS_WINDOWS - COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag); -#endif - COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag); - - COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag); - COPY_NOT_FLAG(site_import, Py_NoSiteFlag); - COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag); - COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory); - - /* Random or non-zero hash seed */ - Py_HashRandomizationFlag = (config->use_hash_seed == 0 || - config->hash_seed != 0); - -#undef COPY_FLAG -#undef COPY_NOT_FLAG -} - - -/* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ - environment variables on macOS if available. */ -static _PyInitError -config_init_program_name(_PyCoreConfig *config) -{ - _PyInitError err; - - /* If Py_SetProgramName() was called, use its value */ - const wchar_t *program_name = _Py_path_config.program_name; - if (program_name != NULL) { - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); - } - -#ifdef __APPLE__ - /* On MacOS X, when the Python interpreter is embedded in an - application bundle, it gets executed by a bootstrapping script - that does os.execve() with an argv[0] that's different from the - actual Python executable. This is needed to keep the Finder happy, - or rather, to work around Apple's overly strict requirements of - the process name. However, we still need a usable sys.executable, - so the actual executable path is passed in an environment variable. - See Lib/plat-mac/bundlebuiler.py for details about the bootstrap - script. */ - const char *p = _PyCoreConfig_GetEnv(config, "PYTHONEXECUTABLE"); - if (p != NULL) { - err = CONFIG_DECODE_LOCALE(config, &config->program_name, p, - "PYTHONEXECUTABLE environment variable"); - if (_Py_INIT_FAILED(err)) { - return err; - } - return _Py_INIT_OK(); - } -#ifdef WITH_NEXT_FRAMEWORK - else { - const char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__"); - if (pyvenv_launcher && *pyvenv_launcher) { - /* Used by Mac/Tools/pythonw.c to forward - * the argv0 of the stub executable - */ - err = CONFIG_DECODE_LOCALE(config, - &config->program_name, pyvenv_launcher, - "__PYVENV_LAUNCHER__ environment variable"); - if (_Py_INIT_FAILED(err)) { - return err; - } - return _Py_INIT_OK(); - } - } -#endif /* WITH_NEXT_FRAMEWORK */ -#endif /* __APPLE__ */ - - /* Use argv[0] if available and non-empty */ - const _PyWstrList *argv = &config->argv; - if (argv->length >= 1 && argv->items[0][0] != L'\0') { - config->program_name = _PyMem_RawWcsdup(argv->items[0]); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); - } - - /* Last fall back: hardcoded name */ -#ifdef MS_WINDOWS - const wchar_t *default_program_name = L"python"; -#else - const wchar_t *default_program_name = L"python3"; -#endif - err = _PyCoreConfig_SetString(config, &config->program_name, - default_program_name); - if (_Py_INIT_FAILED(err)) { - return err; - } - return _Py_INIT_OK(); -} - -static _PyInitError -config_init_executable(_PyCoreConfig *config) -{ - assert(config->executable == NULL); - - /* If Py_SetProgramFullPath() was called, use its value */ - const wchar_t *program_full_path = _Py_path_config.program_full_path; - if (program_full_path != NULL) { - _PyInitError err = _PyCoreConfig_SetString(config, - &config->executable, - program_full_path); - if (_Py_INIT_FAILED(err)) { - return err; - } - return _Py_INIT_OK(); - } - return _Py_INIT_OK(); -} - - -static const wchar_t* -config_get_xoption(const _PyCoreConfig *config, wchar_t *name) -{ - return _Py_get_xoption(&config->xoptions, name); -} - - -static _PyInitError -config_init_home(_PyCoreConfig *config) -{ - assert(config->home == NULL); - - /* If Py_SetPythonHome() was called, use its value */ - wchar_t *home = _Py_path_config.home; - if (home) { - _PyInitError err = _PyCoreConfig_SetString(config, &config->home, home); - if (_Py_INIT_FAILED(err)) { - return err; - } - return _Py_INIT_OK(); - } - - return CONFIG_GET_ENV_DUP(config, &config->home, - L"PYTHONHOME", "PYTHONHOME"); -} - - -static _PyInitError -config_init_hash_seed(_PyCoreConfig *config) -{ - const char *seed_text = _PyCoreConfig_GetEnv(config, "PYTHONHASHSEED"); - - Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc)); - /* Convert a text seed to a numeric one */ - if (seed_text && strcmp(seed_text, "random") != 0) { - const char *endptr = seed_text; - unsigned long seed; - errno = 0; - seed = strtoul(seed_text, (char **)&endptr, 10); - if (*endptr != '\0' - || seed > 4294967295UL - || (errno == ERANGE && seed == ULONG_MAX)) - { - return _Py_INIT_ERR("PYTHONHASHSEED must be \"random\" " - "or an integer in range [0; 4294967295]"); - } - /* Use a specific hash */ - config->use_hash_seed = 1; - config->hash_seed = seed; - } - else { - /* Use a random hash */ - config->use_hash_seed = 0; - config->hash_seed = 0; - } - return _Py_INIT_OK(); -} - - -static int -config_wstr_to_int(const wchar_t *wstr, int *result) -{ - const wchar_t *endptr = wstr; - errno = 0; - long value = wcstol(wstr, (wchar_t **)&endptr, 10); - if (*endptr != '\0' || errno == ERANGE) { - return -1; - } - if (value < INT_MIN || value > INT_MAX) { - return -1; - } - - *result = (int)value; - return 0; -} - - -static _PyInitError -config_read_env_vars(_PyCoreConfig *config) -{ - _PyInitError err; - int use_env = config->use_environment; - - /* Get environment variables */ - _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG"); - _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE"); - _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE"); - _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT"); - - int dont_write_bytecode = 0; - _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); - if (dont_write_bytecode) { - config->write_bytecode = 0; - } - - int no_user_site_directory = 0; - _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE"); - if (no_user_site_directory) { - config->user_site_directory = 0; - } - - int unbuffered_stdio = 0; - _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED"); - if (unbuffered_stdio) { - config->buffered_stdio = 0; - } - -#ifdef MS_WINDOWS - _Py_get_env_flag(use_env, &config->legacy_windows_stdio, - "PYTHONLEGACYWINDOWSSTDIO"); -#endif - - if (_PyCoreConfig_GetEnv(config, "PYTHONDUMPREFS")) { - config->dump_refs = 1; - } - if (_PyCoreConfig_GetEnv(config, "PYTHONMALLOCSTATS")) { - config->malloc_stats = 1; - } - - if (config->module_search_path_env == NULL) { - err = CONFIG_GET_ENV_DUP(config, &config->module_search_path_env, - L"PYTHONPATH", "PYTHONPATH"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->use_hash_seed < 0) { - err = config_init_hash_seed(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - return _Py_INIT_OK(); -} - - -static _PyInitError -config_init_tracemalloc(_PyCoreConfig *config) -{ - int nframe; - int valid; - - const char *env = _PyCoreConfig_GetEnv(config, "PYTHONTRACEMALLOC"); - if (env) { - if (!_Py_str_to_int(env, &nframe)) { - valid = (nframe >= 0); - } - else { - valid = 0; - } - if (!valid) { - return _Py_INIT_ERR("PYTHONTRACEMALLOC: invalid number of frames"); - } - config->tracemalloc = nframe; - } - - const wchar_t *xoption = config_get_xoption(config, L"tracemalloc"); - if (xoption) { - const wchar_t *sep = wcschr(xoption, L'='); - if (sep) { - if (!config_wstr_to_int(sep + 1, &nframe)) { - valid = (nframe >= 0); - } - else { - valid = 0; - } - if (!valid) { - return _Py_INIT_ERR("-X tracemalloc=NFRAME: " - "invalid number of frames"); - } - } - else { - /* -X tracemalloc behaves as -X tracemalloc=1 */ - nframe = 1; - } - config->tracemalloc = nframe; - } - return _Py_INIT_OK(); -} - - -static _PyInitError -config_init_pycache_prefix(_PyCoreConfig *config) -{ - assert(config->pycache_prefix == NULL); - - const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix"); - if (xoption) { - const wchar_t *sep = wcschr(xoption, L'='); - if (sep && wcslen(sep) > 1) { - config->pycache_prefix = _PyMem_RawWcsdup(sep + 1); - if (config->pycache_prefix == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - else { - // PYTHONPYCACHEPREFIX env var ignored - // if "-X pycache_prefix=" option is used - config->pycache_prefix = NULL; - } - return _Py_INIT_OK(); - } - - return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix, - L"PYTHONPYCACHEPREFIX", - "PYTHONPYCACHEPREFIX"); -} - - -static _PyInitError -config_read_complex_options(_PyCoreConfig *config) -{ - /* More complex options configured by env var and -X option */ - if (config->faulthandler < 0) { - if (_PyCoreConfig_GetEnv(config, "PYTHONFAULTHANDLER") - || config_get_xoption(config, L"faulthandler")) { - config->faulthandler = 1; - } - } - if (_PyCoreConfig_GetEnv(config, "PYTHONPROFILEIMPORTTIME") - || config_get_xoption(config, L"importtime")) { - config->import_time = 1; - } - - _PyInitError err; - if (config->tracemalloc < 0) { - err = config_init_tracemalloc(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->pycache_prefix == NULL) { - err = config_init_pycache_prefix(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - return _Py_INIT_OK(); -} - - -static const wchar_t * -config_get_stdio_errors(const _PyCoreConfig *config) -{ -#ifndef MS_WINDOWS - const char *loc = setlocale(LC_CTYPE, NULL); - if (loc != NULL) { - /* surrogateescape is the default in the legacy C and POSIX locales */ - if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) { - return L"surrogateescape"; - } - -#ifdef PY_COERCE_C_LOCALE - /* surrogateescape is the default in locale coercion target locales */ - if (_Py_IsLocaleCoercionTarget(loc)) { - return L"surrogateescape"; - } -#endif - } - - return L"strict"; -#else - /* On Windows, always use surrogateescape by default */ - return L"surrogateescape"; -#endif -} - - -static _PyInitError -config_get_locale_encoding(_PyCoreConfig *config, wchar_t **locale_encoding) -{ -#ifdef MS_WINDOWS - char encoding[20]; - PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); - return _PyCoreConfig_DecodeLocale(config, locale_encoding, encoding); -#elif defined(_Py_FORCE_UTF8_LOCALE) - return _PyCoreConfig_SetString(config, locale_encoding, L"utf-8"); -#else - const char *encoding = nl_langinfo(CODESET); - if (!encoding || encoding[0] == '\0') { - return _Py_INIT_ERR("failed to get the locale encoding: " - "nl_langinfo(CODESET) failed"); - } - /* nl_langinfo(CODESET) is decoded by Py_DecodeLocale() */ - return CONFIG_DECODE_LOCALE(config, - locale_encoding, encoding, - "nl_langinfo(CODESET)"); -#endif -} - - -static _PyInitError -config_init_stdio_encoding(_PyCoreConfig *config, - const _PyPreConfig *preconfig) -{ - _PyInitError err; - - /* If Py_SetStandardStreamEncoding() have been called, use these - parameters. */ - if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) { - err = CONFIG_DECODE_LOCALE(config, &config->stdio_encoding, - _Py_StandardStreamEncoding, - "_Py_StandardStreamEncoding"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) { - err = CONFIG_DECODE_LOCALE(config, &config->stdio_errors, - _Py_StandardStreamErrors, - "_Py_StandardStreamErrors"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->stdio_encoding != NULL && config->stdio_errors != NULL) { - return _Py_INIT_OK(); - } - - /* PYTHONIOENCODING environment variable */ - const char *opt = _PyCoreConfig_GetEnv(config, "PYTHONIOENCODING"); - if (opt) { - char *pythonioencoding = _PyMem_RawStrdup(opt); - if (pythonioencoding == NULL) { - return _Py_INIT_NO_MEMORY(); - } - - char *errors = strchr(pythonioencoding, ':'); - if (errors) { - *errors = '\0'; - errors++; - if (!errors[0]) { - errors = NULL; - } - } - - /* Does PYTHONIOENCODING contain an encoding? */ - if (pythonioencoding[0]) { - if (config->stdio_encoding == NULL) { - err = CONFIG_DECODE_LOCALE(config, &config->stdio_encoding, - pythonioencoding, - "PYTHONIOENCODING environment variable"); - if (_Py_INIT_FAILED(err)) { - PyMem_RawFree(pythonioencoding); - return err; - } - } - - /* If the encoding is set but not the error handler, - use "strict" error handler by default. - PYTHONIOENCODING=latin1 behaves as - PYTHONIOENCODING=latin1:strict. */ - if (!errors) { - errors = "strict"; - } - } - - if (config->stdio_errors == NULL && errors != NULL) { - err = CONFIG_DECODE_LOCALE(config, &config->stdio_errors, - errors, - "PYTHONIOENCODING environment variable"); - if (_Py_INIT_FAILED(err)) { - PyMem_RawFree(pythonioencoding); - return err; - } - } - - PyMem_RawFree(pythonioencoding); - } - - /* UTF-8 Mode uses UTF-8/surrogateescape */ - if (preconfig->utf8_mode) { - if (config->stdio_encoding == NULL) { - err = _PyCoreConfig_SetString(config, &config->stdio_encoding, L"utf-8"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - if (config->stdio_errors == NULL) { - err = _PyCoreConfig_SetString(config, &config->stdio_errors, - L"surrogateescape"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - } - - /* Choose the default error handler based on the current locale. */ - if (config->stdio_encoding == NULL) { - err = config_get_locale_encoding(config, &config->stdio_encoding); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - if (config->stdio_errors == NULL) { - const wchar_t *errors = config_get_stdio_errors(config); - assert(errors != NULL); - - err = _PyCoreConfig_SetString(config, &config->stdio_errors, errors); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - return _Py_INIT_OK(); -} - - -static _PyInitError -config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) -{ - _PyInitError err; - - if (config->filesystem_encoding == NULL) { -#ifdef _Py_FORCE_UTF8_FS_ENCODING - err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, L"utf-8"); -#else - -#ifdef MS_WINDOWS - if (preconfig->legacy_windows_fs_encoding) { - /* Legacy Windows filesystem encoding: mbcs/replace */ - err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, - L"mbcs"); - } - else -#endif - if (preconfig->utf8_mode) { - err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, - L"utf-8"); - } -#ifndef MS_WINDOWS - else if (_Py_GetForceASCII()) { - err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, - L"ascii"); - } -#endif - else { -#ifdef MS_WINDOWS - /* Windows defaults to utf-8/surrogatepass (PEP 529). */ - err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, - L"utf-8"); -#else - err = config_get_locale_encoding(config, - &config->filesystem_encoding); -#endif - } -#endif /* !_Py_FORCE_UTF8_FS_ENCODING */ - - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->filesystem_errors == NULL) { - const wchar_t *errors; -#ifdef MS_WINDOWS - if (preconfig->legacy_windows_fs_encoding) { - errors = L"replace"; - } - else { - errors = L"surrogatepass"; - } -#else - errors = L"surrogateescape"; -#endif - err = _PyCoreConfig_SetString(config, &config->filesystem_errors, errors); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - return _Py_INIT_OK(); -} - - -static _PyInitError -config_read(_PyCoreConfig *config) -{ - _PyInitError err; - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; - - if (config->use_environment) { - err = config_read_env_vars(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - /* -X options */ - if (config_get_xoption(config, L"showrefcount")) { - config->show_ref_count = 1; - } - if (config_get_xoption(config, L"showalloccount")) { - config->show_alloc_count = 1; - } - - err = config_read_complex_options(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - if (config->home == NULL) { - err = config_init_home(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->executable == NULL) { - err = config_init_executable(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->_install_importlib) { - err = _PyCoreConfig_InitPathConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - /* default values */ - if (config->dev_mode) { - if (config->faulthandler < 0) { - config->faulthandler = 1; - } - } - if (config->faulthandler < 0) { - config->faulthandler = 0; - } - if (config->tracemalloc < 0) { - config->tracemalloc = 0; - } - if (config->use_hash_seed < 0) { - config->use_hash_seed = 0; - config->hash_seed = 0; - } - - if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) { - err = config_init_fs_encoding(config, preconfig); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - err = config_init_stdio_encoding(config, preconfig); - if (_Py_INIT_FAILED(err)) { - return err; - } - - if (config->argv.length < 1) { - /* Ensure at least one (empty) argument is seen */ - if (_PyWstrList_Append(&config->argv, L"") < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - - if (config->check_hash_pycs_mode == NULL) { - err = _PyCoreConfig_SetString(config, &config->check_hash_pycs_mode, - L"default"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->configure_c_stdio < 0) { - config->configure_c_stdio = 1; - } - - return _Py_INIT_OK(); -} - - -static void -config_init_stdio(const _PyCoreConfig *config) -{ -#if defined(MS_WINDOWS) || defined(__CYGWIN__) - /* don't translate newlines (\r\n <=> \n) */ - _setmode(fileno(stdin), O_BINARY); - _setmode(fileno(stdout), O_BINARY); - _setmode(fileno(stderr), O_BINARY); -#endif - - if (!config->buffered_stdio) { -#ifdef HAVE_SETVBUF - setvbuf(stdin, (char *)NULL, _IONBF, BUFSIZ); - setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ); - setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ); -#else /* !HAVE_SETVBUF */ - setbuf(stdin, (char *)NULL); - setbuf(stdout, (char *)NULL); - setbuf(stderr, (char *)NULL); -#endif /* !HAVE_SETVBUF */ - } - else if (config->interactive) { -#ifdef MS_WINDOWS - /* Doesn't have to have line-buffered -- use unbuffered */ - /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */ - setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ); -#else /* !MS_WINDOWS */ -#ifdef HAVE_SETVBUF - setvbuf(stdin, (char *)NULL, _IOLBF, BUFSIZ); - setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ); -#endif /* HAVE_SETVBUF */ -#endif /* !MS_WINDOWS */ - /* Leave stderr alone - it should be unbuffered anyway. */ - } -} - - -/* Write the configuration: - - - set Py_xxx global configuration variables - - initialize C standard streams (stdin, stdout, stderr) */ -void -_PyCoreConfig_Write(const _PyCoreConfig *config, _PyRuntimeState *runtime) -{ - _PyCoreConfig_SetGlobalConfig(config); - - if (config->configure_c_stdio) { - config_init_stdio(config); - } - - /* Write the new pre-configuration into _PyRuntime */ - _PyPreConfig *preconfig = &runtime->preconfig; - preconfig->isolated = config->isolated; - preconfig->use_environment = config->use_environment; - preconfig->dev_mode = config->dev_mode; -} - - -/* --- _PyCoreConfig command line parser -------------------------- */ - -static void -config_usage(int error, const wchar_t* program) -{ - FILE *f = error ? stderr : stdout; - - fprintf(f, usage_line, program); - if (error) - fprintf(f, "Try `python -h' for more information.\n"); - else { - fputs(usage_1, f); - fputs(usage_2, f); - fputs(usage_3, f); - fprintf(f, usage_4, (wint_t)DELIM); - fprintf(f, usage_5, (wint_t)DELIM, PYTHONHOMEHELP); - fputs(usage_6, f); - } -} - - -/* Parse the command line arguments */ -static _PyInitError -config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions, - Py_ssize_t *opt_index) -{ - _PyInitError err; - const _PyWstrList *argv = &config->argv; - int print_version = 0; - const wchar_t* program = config->program_name; - - _PyOS_ResetGetOpt(); - do { - int longindex = -1; - int c = _PyOS_GetOpt(argv->length, argv->items, &longindex); - if (c == EOF) { - break; - } - - if (c == 'c') { - if (config->run_command == NULL) { - /* -c is the last option; following arguments - that look like options are left for the - command to interpret. */ - size_t len = wcslen(_PyOS_optarg) + 1 + 1; - wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len); - if (command == NULL) { - return _Py_INIT_NO_MEMORY(); - } - memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t)); - command[len - 2] = '\n'; - command[len - 1] = 0; - config->run_command = command; - } - break; - } - - if (c == 'm') { - /* -m is the last option; following arguments - that look like options are left for the - module to interpret. */ - if (config->run_module == NULL) { - config->run_module = _PyMem_RawWcsdup(_PyOS_optarg); - if (config->run_module == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - break; - } - - switch (c) { - case 0: - // Handle long option. - assert(longindex == 0); // Only one long option now. - if (wcscmp(_PyOS_optarg, L"always") == 0 - || wcscmp(_PyOS_optarg, L"never") == 0 - || wcscmp(_PyOS_optarg, L"default") == 0) - { - err = _PyCoreConfig_SetString(config, &config->check_hash_pycs_mode, - _PyOS_optarg); - if (_Py_INIT_FAILED(err)) { - return err; - } - } else { - fprintf(stderr, "--check-hash-based-pycs must be one of " - "'default', 'always', or 'never'\n"); - config_usage(1, program); - return _Py_INIT_EXIT(2); - } - break; - - case 'b': - config->bytes_warning++; - break; - - case 'd': - config->parser_debug++; - break; - - case 'i': - config->inspect++; - config->interactive++; - break; - - case 'E': - case 'I': - case 'X': - /* option handled by _PyPreCmdline_Read() */ - break; - - /* case 'J': reserved for Jython */ - - case 'O': - config->optimization_level++; - break; - - case 'B': - config->write_bytecode = 0; - break; - - case 's': - config->user_site_directory = 0; - break; - - case 'S': - config->site_import = 0; - break; - - case 't': - /* ignored for backwards compatibility */ - break; - - case 'u': - config->buffered_stdio = 0; - break; - - case 'v': - config->verbose++; - break; - - case 'x': - config->skip_source_first_line = 1; - break; - - case 'h': - case '?': - config_usage(0, program); - return _Py_INIT_EXIT(0); - - case 'V': - print_version++; - break; - - case 'W': - if (_PyWstrList_Append(warnoptions, _PyOS_optarg) < 0) { - return _Py_INIT_NO_MEMORY(); - } - break; - - case 'q': - config->quiet++; - break; - - case 'R': - config->use_hash_seed = 0; - break; - - /* This space reserved for other options */ - - default: - /* unknown argument: parsing failed */ - config_usage(1, program); - return _Py_INIT_EXIT(2); - } - } while (1); - - if (print_version) { - printf("Python %s\n", - (print_version >= 2) ? Py_GetVersion() : PY_VERSION); - return _Py_INIT_EXIT(0); - } - - if (config->run_command == NULL && config->run_module == NULL - && _PyOS_optind < argv->length - && wcscmp(argv->items[_PyOS_optind], L"-") != 0 - && config->run_filename == NULL) - { - config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]); - if (config->run_filename == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - - if (config->run_command != NULL || config->run_module != NULL) { - /* Backup _PyOS_optind */ - _PyOS_optind--; - } - - *opt_index = _PyOS_optind; - - return _Py_INIT_OK(); -} - - -#ifdef MS_WINDOWS -# define WCSTOK wcstok_s -#else -# define WCSTOK wcstok -#endif - -/* Get warning options from PYTHONWARNINGS environment variable. */ -static _PyInitError -config_init_env_warnoptions(_PyCoreConfig *config, _PyWstrList *warnoptions) -{ - _PyInitError err; - /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */ - wchar_t *env = NULL; - err = CONFIG_GET_ENV_DUP(config, &env, - L"PYTHONWARNINGS", "PYTHONWARNINGS"); - if (_Py_INIT_FAILED(err)) { - return err; - } - - /* env var is not set or is empty */ - if (env == NULL) { - return _Py_INIT_OK(); - } - - - wchar_t *warning, *context = NULL; - for (warning = WCSTOK(env, L",", &context); - warning != NULL; - warning = WCSTOK(NULL, L",", &context)) - { - if (_PyWstrList_Append(warnoptions, warning) < 0) { - PyMem_RawFree(env); - return _Py_INIT_NO_MEMORY(); - } - } - PyMem_RawFree(env); - return _Py_INIT_OK(); -} - - -static int -config_add_warnoption(_PyCoreConfig *config, const wchar_t *option) -{ - if (_PyWstrList_Find(&config->warnoptions, option)) { - /* Already present: do nothing */ - return 0; - } - if (_PyWstrList_Append(&config->warnoptions, option)) { - return -1; - } - return 0; -} - - -static _PyInitError -config_init_warnoptions(_PyCoreConfig *config, - const _PyWstrList *cmdline_warnoptions, - const _PyWstrList *env_warnoptions) -{ - /* The priority order for warnings configuration is (highest precedence - * first): - * - * - the BytesWarning filter, if needed ('-b', '-bb') - * - any '-W' command line options; then - * - the 'PYTHONWARNINGS' environment variable; then - * - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then - * - any implicit filters added by _warnings.c/warnings.py - * - * All settings except the last are passed to the warnings module via - * the `sys.warnoptions` list. Since the warnings module works on the basis - * of "the most recently added filter will be checked first", we add - * the lowest precedence entries first so that later entries override them. - */ - - if (config->dev_mode) { - if (config_add_warnoption(config, L"default") < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - - Py_ssize_t i; - const _PyWstrList *options; - - options = env_warnoptions; - for (i = 0; i < options->length; i++) { - if (config_add_warnoption(config, options->items[i]) < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - - options = cmdline_warnoptions; - for (i = 0; i < options->length; i++) { - if (config_add_warnoption(config, options->items[i]) < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - - /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c - * don't even try to emit a warning, so we skip setting the filter in that - * case. - */ - if (config->bytes_warning) { - const wchar_t *filter; - if (config->bytes_warning> 1) { - filter = L"error::BytesWarning"; - } - else { - filter = L"default::BytesWarning"; - } - if (config_add_warnoption(config, filter) < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - return _Py_INIT_OK(); -} - - -static _PyInitError -config_update_argv(_PyCoreConfig *config, Py_ssize_t opt_index) -{ - const _PyWstrList *cmdline_argv = &config->argv; - _PyWstrList config_argv = _PyWstrList_INIT; - - /* Copy argv to be able to modify it (to force -c/-m) */ - if (cmdline_argv->length <= opt_index) { - /* Ensure at least one (empty) argument is seen */ - if (_PyWstrList_Append(&config_argv, L"") < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - else { - _PyWstrList slice; - slice.length = cmdline_argv->length - opt_index; - slice.items = &cmdline_argv->items[opt_index]; - if (_PyWstrList_Copy(&config_argv, &slice) < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - assert(config_argv.length >= 1); - - wchar_t *arg0 = NULL; - if (config->run_command != NULL) { - /* Force sys.argv[0] = '-c' */ - arg0 = L"-c"; - } - else if (config->run_module != NULL) { - /* Force sys.argv[0] = '-m'*/ - arg0 = L"-m"; - } - if (arg0 != NULL) { - arg0 = _PyMem_RawWcsdup(arg0); - if (arg0 == NULL) { - _PyWstrList_Clear(&config_argv); - return _Py_INIT_NO_MEMORY(); - } - - PyMem_RawFree(config_argv.items[0]); - config_argv.items[0] = arg0; - } - - _PyWstrList_Clear(&config->argv); - config->argv = config_argv; - return _Py_INIT_OK(); -} - - -static _PyInitError -core_read_precmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) -{ - _PyInitError err; - - if (config->parse_argv) { - if (_PyWstrList_Copy(&precmdline->argv, &config->argv) < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - - _PyPreConfig preconfig; - _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig); - - _PyPreConfig_GetCoreConfig(&preconfig, config); - - err = _PyPreCmdline_Read(precmdline, &preconfig); - if (_Py_INIT_FAILED(err)) { - return err; - } - - if (_PyPreCmdline_SetCoreConfig(precmdline, config) < 0) { - err = _Py_INIT_NO_MEMORY(); - return err; - } - - return _Py_INIT_OK(); -} - - -static _PyInitError -config_read_cmdline(_PyCoreConfig *config) -{ - _PyInitError err; - _PyWstrList cmdline_warnoptions = _PyWstrList_INIT; - _PyWstrList env_warnoptions = _PyWstrList_INIT; - - if (config->parse_argv < 0) { - config->parse_argv = 1; - } - - if (config->program_name == NULL) { - err = config_init_program_name(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - - if (config->parse_argv) { - Py_ssize_t opt_index; - err = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index); - if (_Py_INIT_FAILED(err)) { - goto done; - } - - err = config_update_argv(config, opt_index); - if (_Py_INIT_FAILED(err)) { - goto done; - } - } - - if (config->use_environment) { - err = config_init_env_warnoptions(config, &env_warnoptions); - if (_Py_INIT_FAILED(err)) { - goto done; - } - } - - err = config_init_warnoptions(config, - &cmdline_warnoptions, &env_warnoptions); - if (_Py_INIT_FAILED(err)) { - goto done; - } - - err = _Py_INIT_OK(); - -done: - _PyWstrList_Clear(&cmdline_warnoptions); - _PyWstrList_Clear(&env_warnoptions); - return err; -} - - -_PyInitError -_PyCoreConfig_SetPyArgv(_PyCoreConfig *config, const _PyArgv *args) -{ - _PyInitError err = _Py_PreInitializeFromCoreConfig(config, args); - if (_Py_INIT_FAILED(err)) { - return err; - } - - return _PyArgv_AsWstrList(args, &config->argv); -} - - -/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python - if needed to ensure that encodings are properly configured. */ -_PyInitError -_PyCoreConfig_SetArgv(_PyCoreConfig *config, Py_ssize_t argc, char * const *argv) -{ - _PyArgv args = { - .argc = argc, - .use_bytes_argv = 1, - .bytes_argv = argv, - .wchar_argv = NULL}; - return _PyCoreConfig_SetPyArgv(config, &args); -} - - -_PyInitError -_PyCoreConfig_SetWideArgv(_PyCoreConfig *config, Py_ssize_t argc, wchar_t * const *argv) -{ - _PyArgv args = { - .argc = argc, - .use_bytes_argv = 0, - .bytes_argv = NULL, - .wchar_argv = argv}; - return _PyCoreConfig_SetPyArgv(config, &args); -} - - -/* Read the configuration into _PyCoreConfig from: - - * Command line arguments - * Environment variables - * Py_xxx global configuration variables - - The only side effects are to modify config and to call _Py_SetArgcArgv(). */ -_PyInitError -_PyCoreConfig_Read(_PyCoreConfig *config) -{ - _PyInitError err; - _PyWstrList orig_argv = _PyWstrList_INIT; - - err = _Py_PreInitializeFromCoreConfig(config, NULL); - if (_Py_INIT_FAILED(err)) { - return err; - } - - _PyCoreConfig_GetGlobalConfig(config); - - if (_PyWstrList_Copy(&orig_argv, &config->argv) < 0) { - return _Py_INIT_NO_MEMORY(); - } - - _PyPreCmdline precmdline = _PyPreCmdline_INIT; - err = core_read_precmdline(config, &precmdline); - if (_Py_INIT_FAILED(err)) { - goto done; - } - - assert(config->isolated >= 0); - if (config->isolated) { - config->use_environment = 0; - config->user_site_directory = 0; - } - - err = config_read_cmdline(config); - if (_Py_INIT_FAILED(err)) { - goto done; - } - - err = config_read(config); - if (_Py_INIT_FAILED(err)) { - goto done; - } - - if (_Py_SetArgcArgv(orig_argv.length, orig_argv.items) < 0) { - err = _Py_INIT_NO_MEMORY(); - goto done; - } - - /* Check config consistency */ - assert(config->isolated >= 0); - assert(config->use_environment >= 0); - assert(config->dev_mode >= 0); - assert(config->install_signal_handlers >= 0); - assert(config->use_hash_seed >= 0); - assert(config->faulthandler >= 0); - assert(config->tracemalloc >= 0); - assert(config->site_import >= 0); - assert(config->bytes_warning >= 0); - assert(config->inspect >= 0); - assert(config->interactive >= 0); - assert(config->optimization_level >= 0); - assert(config->parser_debug >= 0); - assert(config->write_bytecode >= 0); - assert(config->verbose >= 0); - assert(config->quiet >= 0); - assert(config->user_site_directory >= 0); - assert(config->parse_argv >= 0); - assert(config->configure_c_stdio >= 0); - assert(config->buffered_stdio >= 0); - assert(config->program_name != NULL); - assert(_PyWstrList_CheckConsistency(&config->argv)); - /* sys.argv must be non-empty: empty argv is replaced with [''] */ - assert(config->argv.length >= 1); - assert(_PyWstrList_CheckConsistency(&config->xoptions)); - assert(_PyWstrList_CheckConsistency(&config->warnoptions)); - assert(_PyWstrList_CheckConsistency(&config->module_search_paths)); - if (config->_install_importlib) { - assert(config->use_module_search_paths != 0); - /* don't check config->module_search_paths */ - assert(config->executable != NULL); - assert(config->prefix != NULL); - assert(config->base_prefix != NULL); - assert(config->exec_prefix != NULL); - assert(config->base_exec_prefix != NULL); - } - assert(config->filesystem_encoding != NULL); - assert(config->filesystem_errors != NULL); - assert(config->stdio_encoding != NULL); - assert(config->stdio_errors != NULL); -#ifdef MS_WINDOWS - assert(config->legacy_windows_stdio >= 0); -#endif - /* -c and -m options are exclusive */ - assert(!(config->run_command != NULL && config->run_module != NULL)); - assert(config->check_hash_pycs_mode != NULL); - assert(config->_install_importlib >= 0); - assert(config->pathconfig_warnings >= 0); - - err = _Py_INIT_OK(); - -done: - _PyWstrList_Clear(&orig_argv); - _PyPreCmdline_Clear(&precmdline); - return err; -} - - -PyObject* -_Py_GetConfigsAsDict(void) -{ - PyObject *config = NULL; - PyObject *dict = NULL; - - config = PyDict_New(); - if (config == NULL) { - goto error; - } - - /* global config */ - dict = _Py_GetGlobalVariablesAsDict(); - if (dict == NULL) { - goto error; - } - if (PyDict_SetItemString(config, "global_config", dict) < 0) { - goto error; - } - Py_CLEAR(dict); - - /* pre config */ - PyInterpreterState *interp = _PyInterpreterState_Get(); - const _PyPreConfig *pre_config = &_PyRuntime.preconfig; - dict = _PyPreConfig_AsDict(pre_config); - if (dict == NULL) { - goto error; - } - if (PyDict_SetItemString(config, "pre_config", dict) < 0) { - goto error; - } - Py_CLEAR(dict); - - /* core config */ - const _PyCoreConfig *core_config = _PyInterpreterState_GetCoreConfig(interp); - dict = _PyCoreConfig_AsDict(core_config); - if (dict == NULL) { - goto error; - } - if (PyDict_SetItemString(config, "core_config", dict) < 0) { - goto error; - } - Py_CLEAR(dict); - - return config; - -error: - Py_XDECREF(config); - Py_XDECREF(dict); - return NULL; -} diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c index f275e53..da9baa4 100644 --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -20,7 +20,7 @@ dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, const char *pathname, FILE *fp) { int flags = BIND_FIRST | BIND_DEFERRED; - int verbose = _PyInterpreterState_GET_UNSAFE()->core_config.verbose; + int verbose = _PyInterpreterState_GET_UNSAFE()->config.verbose; if (verbose) { flags = BIND_FIRST | BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE; diff --git a/Python/errors.c b/Python/errors.c index 831f111..bd33d4d 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -2,7 +2,7 @@ /* Error handling */ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" #include "pycore_traceback.h" @@ -1090,16 +1090,16 @@ static PyStructSequence_Desc UnraisableHookArgs_desc = { }; -_PyInitError +PyStatus _PyErr_Init(void) { if (UnraisableHookArgsType.tp_name == NULL) { if (PyStructSequence_InitType2(&UnraisableHookArgsType, &UnraisableHookArgs_desc) < 0) { - return _Py_INIT_ERR("failed to initialize UnraisableHookArgs type"); + return _PyStatus_ERR("failed to initialize UnraisableHookArgs type"); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } diff --git a/Python/frozenmain.c b/Python/frozenmain.c index c3af080..c56938a 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -16,9 +16,9 @@ extern int PyInitFrozenExtensions(void); int Py_FrozenMain(int argc, char **argv) { - _PyInitError err = _PyRuntime_Initialize(); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + PyStatus status = _PyRuntime_Initialize(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } const char *p; @@ -39,11 +39,11 @@ Py_FrozenMain(int argc, char **argv) } } - _PyCoreConfig config; - err = _PyCoreConfig_InitPythonConfig(&config); - if (_PyInitError_Failed(err)) { - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + PyConfig config; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); } config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */ @@ -85,10 +85,10 @@ Py_FrozenMain(int argc, char **argv) if (argc >= 1) Py_SetProgramName(argv_copy[0]); - err = _Py_InitializeFromConfig(&config); - _PyCoreConfig_Clear(&config); - if (_PyInitError_Failed(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); } #ifdef MS_WINDOWS diff --git a/Python/import.c b/Python/import.c index ec172b2..41a5c01 100644 --- a/Python/import.c +++ b/Python/import.c @@ -43,17 +43,17 @@ module _imp /* Initialize things */ -_PyInitError +PyStatus _PyImport_Init(PyInterpreterState *interp) { interp->builtins_copy = PyDict_Copy(interp->builtins); if (interp->builtins_copy == NULL) { - return _Py_INIT_ERR("Can't backup builtins dict"); + return _PyStatus_ERR("Can't backup builtins dict"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError +PyStatus _PyImportHooks_Init(void) { PyObject *v, *path_hooks = NULL; @@ -82,15 +82,15 @@ _PyImportHooks_Init(void) goto error; } Py_DECREF(path_hooks); - return _Py_INIT_OK(); + return _PyStatus_OK(); error: PyErr_Print(); - return _Py_INIT_ERR("initializing sys.meta_path, sys.path_hooks, " + return _PyStatus_ERR("initializing sys.meta_path, sys.path_hooks, " "or path_importer_cache failed"); } -_PyInitError +PyStatus _PyImportZip_Init(PyInterpreterState *interp) { PyObject *path_hooks, *zipimport; @@ -102,7 +102,7 @@ _PyImportZip_Init(PyInterpreterState *interp) goto error; } - int verbose = interp->core_config.verbose; + int verbose = interp->config.verbose; if (verbose) { PySys_WriteStderr("# installing zipimport hook\n"); } @@ -138,11 +138,11 @@ _PyImportZip_Init(PyInterpreterState *interp) } } - return _Py_INIT_OK(); + return _PyStatus_OK(); error: PyErr_Print(); - return _Py_INIT_ERR("initializing zipimport failed"); + return _PyStatus_ERR("initializing zipimport failed"); } /* Locking primitives to prevent parallel imports of the same module @@ -418,7 +418,7 @@ PyImport_Cleanup(void) /* XXX Perhaps these precautions are obsolete. Who knows? */ - int verbose = interp->core_config.verbose; + int verbose = interp->config.verbose; if (verbose) { PySys_WriteStderr("# clear builtins._\n"); } @@ -766,7 +766,7 @@ _PyImport_FindExtensionObjectEx(PyObject *name, PyObject *filename, PyMapping_DelItem(modules, name); return NULL; } - int verbose = _PyInterpreterState_Get()->core_config.verbose; + int verbose = _PyInterpreterState_Get()->config.verbose; if (verbose) { PySys_FormatStderr("import %U # previously loaded (%R)\n", name, filename); @@ -1455,7 +1455,7 @@ remove_importlib_frames(PyInterpreterState *interp) which end with a call to "_call_with_frames_removed". */ PyErr_Fetch(&exception, &value, &base_tb); - if (!exception || interp->core_config.verbose) { + if (!exception || interp->config.verbose) { goto done; } @@ -1655,7 +1655,7 @@ import_find_and_load(PyObject *abs_name) _Py_IDENTIFIER(_find_and_load); PyObject *mod = NULL; PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - int import_time = interp->core_config.import_time; + int import_time = interp->config.import_time; static int import_level; static _PyTime_t accumulated; @@ -2338,7 +2338,7 @@ PyInit__imp(void) goto failure; } - const wchar_t *mode = _PyInterpreterState_Get()->core_config.check_hash_pycs_mode; + const wchar_t *mode = _PyInterpreterState_Get()->config.check_hash_pycs_mode; PyObject *pyc_mode = PyUnicode_FromWideChar(mode, -1); if (pyc_mode == NULL) { goto failure; diff --git a/Python/initconfig.c b/Python/initconfig.c new file mode 100644 index 0000000..66b1b30 --- /dev/null +++ b/Python/initconfig.c @@ -0,0 +1,2437 @@ +#include "Python.h" +#include "osdefs.h" /* DELIM */ +#include "pycore_initconfig.h" +#include "pycore_fileutils.h" +#include "pycore_getopt.h" +#include "pycore_pylifecycle.h" +#include "pycore_pymem.h" +#include "pycore_pystate.h" /* _PyRuntime */ +#include "pycore_pathconfig.h" +#include /* setlocale() */ +#ifdef HAVE_LANGINFO_H +# include /* nl_langinfo(CODESET) */ +#endif +#if defined(MS_WINDOWS) || defined(__CYGWIN__) +# include /* GetACP() */ +# ifdef HAVE_IO_H +# include +# endif +# ifdef HAVE_FCNTL_H +# include /* O_BINARY */ +# endif +#endif + + +/* --- Command line options --------------------------------------- */ + +/* Short usage message (with %s for argv0) */ +static const char usage_line[] = +"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n"; + +/* Long usage message, split into parts < 512 bytes */ +static const char usage_1[] = "\ +Options and arguments (and corresponding environment variables):\n\ +-b : issue warnings about str(bytes_instance), str(bytearray_instance)\n\ + and comparing bytes/bytearray with str. (-bb: issue errors)\n\ +-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\ +-c cmd : program passed in as string (terminates option list)\n\ +-d : debug output from parser; also PYTHONDEBUG=x\n\ +-E : ignore PYTHON* environment variables (such as PYTHONPATH)\n\ +-h : print this help message and exit (also --help)\n\ +"; +static const char usage_2[] = "\ +-i : inspect interactively after running script; forces a prompt even\n\ + if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\ +-I : isolate Python from the user's environment (implies -E and -s)\n\ +-m mod : run library module as a script (terminates option list)\n\ +-O : remove assert and __debug__-dependent statements; add .opt-1 before\n\ + .pyc extension; also PYTHONOPTIMIZE=x\n\ +-OO : do -O changes and also discard docstrings; add .opt-2 before\n\ + .pyc extension\n\ +-q : don't print version and copyright messages on interactive startup\n\ +-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ +-S : don't imply 'import site' on initialization\n\ +"; +static const char usage_3[] = "\ +-u : force the stdout and stderr streams to be unbuffered;\n\ + this option has no effect on stdin; also PYTHONUNBUFFERED=x\n\ +-v : verbose (trace import statements); also PYTHONVERBOSE=x\n\ + can be supplied multiple times to increase verbosity\n\ +-V : print the Python version number and exit (also --version)\n\ + when given twice, print more information about the build\n\ +-W arg : warning control; arg is action:message:category:module:lineno\n\ + also PYTHONWARNINGS=arg\n\ +-x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\ +-X opt : set implementation-specific option\n\ +--check-hash-based-pycs always|default|never:\n\ + control how Python invalidates hash-based .pyc files\n\ +"; +static const char usage_4[] = "\ +file : program read from script file\n\ +- : program read from stdin (default; interactive mode if a tty)\n\ +arg ...: arguments passed to program in sys.argv[1:]\n\n\ +Other environment variables:\n\ +PYTHONSTARTUP: file executed on interactive startup (no default)\n\ +PYTHONPATH : '%lc'-separated list of directories prefixed to the\n\ + default module search path. The result is sys.path.\n\ +"; +static const char usage_5[] = +"PYTHONHOME : alternate directory (or %lc).\n" +" The default module search path uses %s.\n" +"PYTHONCASEOK : ignore case in 'import' statements (Windows).\n" +"PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n" +"PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n"; +static const char usage_6[] = +"PYTHONHASHSEED: if this variable is set to 'random', a random value is used\n" +" to seed the hashes of str, bytes and datetime objects. It can also be\n" +" set to an integer in the range [0,4294967295] to get hash values with a\n" +" predictable seed.\n" +"PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n" +" on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n" +" hooks.\n" +"PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n" +" coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of\n" +" locale coercion and locale compatibility warnings on stderr.\n" +"PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n" +" debugger. It can be set to the callable of your debugger of choice.\n" +"PYTHONDEVMODE: enable the development mode.\n" +"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n"; + +#if defined(MS_WINDOWS) +# define PYTHONHOMEHELP "\\python{major}{minor}" +#else +# define PYTHONHOMEHELP "/lib/pythonX.X" +#endif + + +/* --- Global configuration variables ----------------------------- */ + +/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change + stdin and stdout error handler to "surrogateescape". */ +int Py_UTF8Mode = 0; +int Py_DebugFlag = 0; /* Needed by parser.c */ +int Py_VerboseFlag = 0; /* Needed by import.c */ +int Py_QuietFlag = 0; /* Needed by sysmodule.c */ +int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */ +int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */ +int Py_OptimizeFlag = 0; /* Needed by compile.c */ +int Py_NoSiteFlag = 0; /* Suppress 'import site' */ +int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */ +int Py_FrozenFlag = 0; /* Needed by getpath.c */ +int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */ +int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */ +int Py_NoUserSiteDirectory = 0; /* for -s and site.py */ +int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */ +int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */ +int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */ +#ifdef MS_WINDOWS +int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */ +int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */ +#endif + + +static PyObject * +_Py_GetGlobalVariablesAsDict(void) +{ + PyObject *dict, *obj; + + dict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + +#define SET_ITEM(KEY, EXPR) \ + do { \ + obj = (EXPR); \ + if (obj == NULL) { \ + return NULL; \ + } \ + int res = PyDict_SetItemString(dict, (KEY), obj); \ + Py_DECREF(obj); \ + if (res < 0) { \ + goto fail; \ + } \ + } while (0) +#define SET_ITEM_INT(VAR) \ + SET_ITEM(#VAR, PyLong_FromLong(VAR)) +#define FROM_STRING(STR) \ + ((STR != NULL) ? \ + PyUnicode_FromString(STR) \ + : (Py_INCREF(Py_None), Py_None)) +#define SET_ITEM_STR(VAR) \ + SET_ITEM(#VAR, FROM_STRING(VAR)) + + SET_ITEM_STR(Py_FileSystemDefaultEncoding); + SET_ITEM_INT(Py_HasFileSystemDefaultEncoding); + SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors); + SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors); + + SET_ITEM_INT(Py_UTF8Mode); + SET_ITEM_INT(Py_DebugFlag); + SET_ITEM_INT(Py_VerboseFlag); + SET_ITEM_INT(Py_QuietFlag); + SET_ITEM_INT(Py_InteractiveFlag); + SET_ITEM_INT(Py_InspectFlag); + + SET_ITEM_INT(Py_OptimizeFlag); + SET_ITEM_INT(Py_NoSiteFlag); + SET_ITEM_INT(Py_BytesWarningFlag); + SET_ITEM_INT(Py_FrozenFlag); + SET_ITEM_INT(Py_IgnoreEnvironmentFlag); + SET_ITEM_INT(Py_DontWriteBytecodeFlag); + SET_ITEM_INT(Py_NoUserSiteDirectory); + SET_ITEM_INT(Py_UnbufferedStdioFlag); + SET_ITEM_INT(Py_HashRandomizationFlag); + SET_ITEM_INT(Py_IsolatedFlag); + +#ifdef MS_WINDOWS + SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag); + SET_ITEM_INT(Py_LegacyWindowsStdioFlag); +#endif + + return dict; + +fail: + Py_DECREF(dict); + return NULL; + +#undef FROM_STRING +#undef SET_ITEM +#undef SET_ITEM_INT +#undef SET_ITEM_STR +} + + +/* --- PyStatus ----------------------------------------------- */ + +PyStatus PyStatus_Ok(void) +{ return _PyStatus_OK(); } + +PyStatus PyStatus_Error(const char *err_msg) +{ + return (PyStatus){._type = _PyStatus_TYPE_ERROR, + .err_msg = err_msg}; +} + +PyStatus PyStatus_NoMemory(void) +{ return PyStatus_Error("memory allocation failed"); } + +PyStatus PyStatus_Exit(int exitcode) +{ return _PyStatus_EXIT(exitcode); } + + +int PyStatus_IsError(PyStatus status) +{ return _PyStatus_IS_ERROR(status); } + +int PyStatus_IsExit(PyStatus status) +{ return _PyStatus_IS_EXIT(status); } + +int PyStatus_Exception(PyStatus status) +{ return _PyStatus_EXCEPTION(status); } + + +/* --- PyWideStringList ------------------------------------------------ */ + +#ifndef NDEBUG +int +_PyWideStringList_CheckConsistency(const PyWideStringList *list) +{ + assert(list->length >= 0); + if (list->length != 0) { + assert(list->items != NULL); + } + for (Py_ssize_t i = 0; i < list->length; i++) { + assert(list->items[i] != NULL); + } + return 1; +} +#endif /* Py_DEBUG */ + + +void +_PyWideStringList_Clear(PyWideStringList *list) +{ + assert(_PyWideStringList_CheckConsistency(list)); + for (Py_ssize_t i=0; i < list->length; i++) { + PyMem_RawFree(list->items[i]); + } + PyMem_RawFree(list->items); + list->length = 0; + list->items = NULL; +} + + +int +_PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2) +{ + assert(_PyWideStringList_CheckConsistency(list)); + assert(_PyWideStringList_CheckConsistency(list2)); + + if (list2->length == 0) { + _PyWideStringList_Clear(list); + return 0; + } + + PyWideStringList copy = PyWideStringList_INIT; + + size_t size = list2->length * sizeof(list2->items[0]); + copy.items = PyMem_RawMalloc(size); + if (copy.items == NULL) { + return -1; + } + + for (Py_ssize_t i=0; i < list2->length; i++) { + wchar_t *item = _PyMem_RawWcsdup(list2->items[i]); + if (item == NULL) { + _PyWideStringList_Clear(©); + return -1; + } + copy.items[i] = item; + copy.length = i + 1; + } + + _PyWideStringList_Clear(list); + *list = copy; + return 0; +} + + +PyStatus +PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) +{ + if (list->length == PY_SSIZE_T_MAX) { + /* lenght+1 would overflow */ + return _PyStatus_NO_MEMORY(); + } + + wchar_t *item2 = _PyMem_RawWcsdup(item); + if (item2 == NULL) { + return _PyStatus_NO_MEMORY(); + } + + size_t size = (list->length + 1) * sizeof(list->items[0]); + wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size); + if (items2 == NULL) { + PyMem_RawFree(item2); + return _PyStatus_NO_MEMORY(); + } + + items2[list->length] = item2; + list->items = items2; + list->length++; + return _PyStatus_OK(); +} + + +PyStatus +_PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2) +{ + for (Py_ssize_t i = 0; i < list2->length; i++) { + PyStatus status = PyWideStringList_Append(list, list2->items[i]); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + return _PyStatus_OK(); +} + + +static int +_PyWideStringList_Find(PyWideStringList *list, const wchar_t *item) +{ + for (Py_ssize_t i = 0; i < list->length; i++) { + if (wcscmp(list->items[i], item) == 0) { + return 1; + } + } + return 0; +} + + +PyObject* +_PyWideStringList_AsList(const PyWideStringList *list) +{ + assert(_PyWideStringList_CheckConsistency(list)); + + PyObject *pylist = PyList_New(list->length); + if (pylist == NULL) { + return NULL; + } + + for (Py_ssize_t i = 0; i < list->length; i++) { + PyObject *item = PyUnicode_FromWideChar(list->items[i], -1); + if (item == NULL) { + Py_DECREF(pylist); + return NULL; + } + PyList_SET_ITEM(pylist, i, item); + } + return pylist; +} + + +/* --- Py_SetStandardStreamEncoding() ----------------------------- */ + +/* Helper to allow an embedding application to override the normal + * mechanism that attempts to figure out an appropriate IO encoding + */ + +static char *_Py_StandardStreamEncoding = NULL; +static char *_Py_StandardStreamErrors = NULL; + +int +Py_SetStandardStreamEncoding(const char *encoding, const char *errors) +{ + if (Py_IsInitialized()) { + /* This is too late to have any effect */ + return -1; + } + + int res = 0; + + /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(), + but Py_Initialize() can change the allocator. Use a known allocator + to be able to release the memory later. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + /* Can't call PyErr_NoMemory() on errors, as Python hasn't been + * initialised yet. + * + * However, the raw memory allocators are initialised appropriately + * as C static variables, so _PyMem_RawStrdup is OK even though + * Py_Initialize hasn't been called yet. + */ + if (encoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); + _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); + if (!_Py_StandardStreamEncoding) { + res = -2; + goto done; + } + } + if (errors) { + PyMem_RawFree(_Py_StandardStreamErrors); + _Py_StandardStreamErrors = _PyMem_RawStrdup(errors); + if (!_Py_StandardStreamErrors) { + PyMem_RawFree(_Py_StandardStreamEncoding); + _Py_StandardStreamEncoding = NULL; + res = -3; + goto done; + } + } +#ifdef MS_WINDOWS + if (_Py_StandardStreamEncoding) { + /* Overriding the stream encoding implies legacy streams */ + Py_LegacyWindowsStdioFlag = 1; + } +#endif + +done: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + return res; +} + + +void +_Py_ClearStandardStreamEncoding(void) +{ + /* Use the same allocator than Py_SetStandardStreamEncoding() */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + /* We won't need them anymore. */ + if (_Py_StandardStreamEncoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); + _Py_StandardStreamEncoding = NULL; + } + if (_Py_StandardStreamErrors) { + PyMem_RawFree(_Py_StandardStreamErrors); + _Py_StandardStreamErrors = NULL; + } + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + +/* --- Py_GetArgcArgv() ------------------------------------------- */ + +/* For Py_GetArgcArgv(); set by _Py_SetArgcArgv() */ +static PyWideStringList orig_argv = {.length = 0, .items = NULL}; + + +void +_Py_ClearArgcArgv(void) +{ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + _PyWideStringList_Clear(&orig_argv); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + +static int +_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv) +{ + const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv}; + int res; + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + res = _PyWideStringList_Copy(&orig_argv, &argv_list); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + return res; +} + + +/* Make the *original* argc/argv available to other modules. + This is rare, but it is needed by the secureware extension. */ +void +Py_GetArgcArgv(int *argc, wchar_t ***argv) +{ + *argc = (int)orig_argv.length; + *argv = orig_argv.items; +} + + +/* --- PyConfig ---------------------------------------------- */ + +#define DECODE_LOCALE_ERR(NAME, LEN) \ + (((LEN) == -2) \ + ? _PyStatus_ERR("cannot decode " NAME) \ + : _PyStatus_NO_MEMORY()) + +/* Free memory allocated in config, but don't clear all attributes */ +void +PyConfig_Clear(PyConfig *config) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->pycache_prefix); + CLEAR(config->pythonpath_env); + CLEAR(config->home); + CLEAR(config->program_name); + + _PyWideStringList_Clear(&config->argv); + _PyWideStringList_Clear(&config->warnoptions); + _PyWideStringList_Clear(&config->xoptions); + _PyWideStringList_Clear(&config->module_search_paths); + config->module_search_paths_set = 0; + + CLEAR(config->executable); + CLEAR(config->prefix); + CLEAR(config->base_prefix); + CLEAR(config->exec_prefix); + CLEAR(config->base_exec_prefix); + + CLEAR(config->filesystem_encoding); + CLEAR(config->filesystem_errors); + CLEAR(config->stdio_encoding); + CLEAR(config->stdio_errors); + CLEAR(config->run_command); + CLEAR(config->run_module); + CLEAR(config->run_filename); + CLEAR(config->check_hash_pycs_mode); +#undef CLEAR +} + + +void +_PyConfig_InitCompatConfig(PyConfig *config) +{ + memset(config, 0, sizeof(*config)); + + config->_config_version = _Py_CONFIG_VERSION; + config->_config_init = (int)_PyConfig_INIT_COMPAT; + config->isolated = -1; + config->use_environment = -1; + config->dev_mode = -1; + config->install_signal_handlers = 1; + config->use_hash_seed = -1; + config->faulthandler = -1; + config->tracemalloc = -1; + config->module_search_paths_set = 0; + config->parse_argv = 0; + config->site_import = -1; + config->bytes_warning = -1; + config->inspect = -1; + config->interactive = -1; + config->optimization_level = -1; + config->parser_debug= -1; + config->write_bytecode = -1; + config->verbose = -1; + config->quiet = -1; + config->user_site_directory = -1; + config->configure_c_stdio = 0; + config->buffered_stdio = -1; + config->_install_importlib = 1; + config->check_hash_pycs_mode = NULL; + config->pathconfig_warnings = -1; + config->_init_main = 1; +#ifdef MS_WINDOWS + config->legacy_windows_stdio = -1; +#endif +} + + +static void +config_init_defaults(PyConfig *config) +{ + _PyConfig_InitCompatConfig(config); + + config->isolated = 0; + config->use_environment = 1; + config->site_import = 1; + config->bytes_warning = 0; + config->inspect = 0; + config->interactive = 0; + config->optimization_level = 0; + config->parser_debug= 0; + config->write_bytecode = 1; + config->verbose = 0; + config->quiet = 0; + config->user_site_directory = 1; + config->buffered_stdio = 1; + config->pathconfig_warnings = 1; +#ifdef MS_WINDOWS + config->legacy_windows_stdio = 0; +#endif +} + + +PyStatus +PyConfig_InitPythonConfig(PyConfig *config) +{ + config_init_defaults(config); + + config->_config_init = (int)_PyConfig_INIT_PYTHON; + config->configure_c_stdio = 1; + config->parse_argv = 1; + + return _PyStatus_OK(); +} + + +PyStatus +PyConfig_InitIsolatedConfig(PyConfig *config) +{ + config_init_defaults(config); + + config->_config_init = (int)_PyConfig_INIT_ISOLATED; + config->isolated = 1; + config->use_environment = 0; + config->user_site_directory = 0; + config->dev_mode = 0; + config->install_signal_handlers = 0; + config->use_hash_seed = 0; + config->faulthandler = 0; + config->tracemalloc = 0; + config->pathconfig_warnings = 0; +#ifdef MS_WINDOWS + config->legacy_windows_stdio = 0; +#endif + + return _PyStatus_OK(); +} + + +/* Copy str into *config_str (duplicate the string) */ +PyStatus +PyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str) +{ + PyStatus status = _Py_PreInitializeFromConfig(config, NULL); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + wchar_t *str2; + if (str != NULL) { + str2 = _PyMem_RawWcsdup(str); + if (str2 == NULL) { + return _PyStatus_NO_MEMORY(); + } + } + else { + str2 = NULL; + } + PyMem_RawFree(*config_str); + *config_str = str2; + return _PyStatus_OK(); +} + + +static PyStatus +config_set_bytes_string(PyConfig *config, wchar_t **config_str, + const char *str, const char *decode_err_msg) +{ + PyStatus status = _Py_PreInitializeFromConfig(config, NULL); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + wchar_t *str2; + if (str != NULL) { + size_t len; + str2 = Py_DecodeLocale(str, &len); + if (str2 == NULL) { + if (len == (size_t)-2) { + return _PyStatus_ERR(decode_err_msg); + } + else { + return _PyStatus_NO_MEMORY(); + } + } + } + else { + str2 = NULL; + } + PyMem_RawFree(*config_str); + *config_str = str2; + return _PyStatus_OK(); +} + + +#define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \ + config_set_bytes_string(config, config_str, str, "cannot decode " NAME) + + +/* Decode str using Py_DecodeLocale() and set the result into *config_str. + Pre-initialize Python if needed to ensure that encodings are properly + configured. */ +PyStatus +PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str, + const char *str) +{ + return CONFIG_SET_BYTES_STR(config, config_str, str, "string"); +} + + +PyStatus +_PyConfig_Copy(PyConfig *config, const PyConfig *config2) +{ + PyStatus status; + PyConfig_Clear(config); + +#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR +#define COPY_WSTR_ATTR(ATTR) \ + do { \ + status = PyConfig_SetString(config, &config->ATTR, config2->ATTR); \ + if (_PyStatus_EXCEPTION(status)) { \ + return status; \ + } \ + } while (0) +#define COPY_WSTRLIST(LIST) \ + do { \ + if (_PyWideStringList_Copy(&config->LIST, &config2->LIST) < 0 ) { \ + return _PyStatus_NO_MEMORY(); \ + } \ + } while (0) + + COPY_ATTR(_config_init); + COPY_ATTR(isolated); + COPY_ATTR(use_environment); + COPY_ATTR(dev_mode); + COPY_ATTR(install_signal_handlers); + COPY_ATTR(use_hash_seed); + COPY_ATTR(hash_seed); + COPY_ATTR(_install_importlib); + COPY_ATTR(faulthandler); + COPY_ATTR(tracemalloc); + COPY_ATTR(import_time); + COPY_ATTR(show_ref_count); + COPY_ATTR(show_alloc_count); + COPY_ATTR(dump_refs); + COPY_ATTR(malloc_stats); + + COPY_WSTR_ATTR(pycache_prefix); + COPY_WSTR_ATTR(pythonpath_env); + COPY_WSTR_ATTR(home); + COPY_WSTR_ATTR(program_name); + + COPY_ATTR(parse_argv); + COPY_WSTRLIST(argv); + COPY_WSTRLIST(warnoptions); + COPY_WSTRLIST(xoptions); + COPY_WSTRLIST(module_search_paths); + COPY_ATTR(module_search_paths_set); + + COPY_WSTR_ATTR(executable); + COPY_WSTR_ATTR(prefix); + COPY_WSTR_ATTR(base_prefix); + COPY_WSTR_ATTR(exec_prefix); + COPY_WSTR_ATTR(base_exec_prefix); + + COPY_ATTR(site_import); + COPY_ATTR(bytes_warning); + COPY_ATTR(inspect); + COPY_ATTR(interactive); + COPY_ATTR(optimization_level); + COPY_ATTR(parser_debug); + COPY_ATTR(write_bytecode); + COPY_ATTR(verbose); + COPY_ATTR(quiet); + COPY_ATTR(user_site_directory); + COPY_ATTR(configure_c_stdio); + COPY_ATTR(buffered_stdio); + COPY_WSTR_ATTR(filesystem_encoding); + COPY_WSTR_ATTR(filesystem_errors); + COPY_WSTR_ATTR(stdio_encoding); + COPY_WSTR_ATTR(stdio_errors); +#ifdef MS_WINDOWS + COPY_ATTR(legacy_windows_stdio); +#endif + COPY_ATTR(skip_source_first_line); + COPY_WSTR_ATTR(run_command); + COPY_WSTR_ATTR(run_module); + COPY_WSTR_ATTR(run_filename); + COPY_WSTR_ATTR(check_hash_pycs_mode); + COPY_ATTR(pathconfig_warnings); + COPY_ATTR(_init_main); + +#undef COPY_ATTR +#undef COPY_WSTR_ATTR +#undef COPY_WSTRLIST + return _PyStatus_OK(); +} + + +static PyObject * +config_as_dict(const PyConfig *config) +{ + PyObject *dict; + + dict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + +#define SET_ITEM(KEY, EXPR) \ + do { \ + PyObject *obj = (EXPR); \ + if (obj == NULL) { \ + goto fail; \ + } \ + int res = PyDict_SetItemString(dict, (KEY), obj); \ + Py_DECREF(obj); \ + if (res < 0) { \ + goto fail; \ + } \ + } while (0) +#define SET_ITEM_INT(ATTR) \ + SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) +#define SET_ITEM_UINT(ATTR) \ + SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR)) +#define FROM_WSTRING(STR) \ + ((STR != NULL) ? \ + PyUnicode_FromWideChar(STR, -1) \ + : (Py_INCREF(Py_None), Py_None)) +#define SET_ITEM_WSTR(ATTR) \ + SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR)) +#define SET_ITEM_WSTRLIST(LIST) \ + SET_ITEM(#LIST, _PyWideStringList_AsList(&config->LIST)) + + SET_ITEM_INT(_config_init); + SET_ITEM_INT(isolated); + SET_ITEM_INT(use_environment); + SET_ITEM_INT(dev_mode); + SET_ITEM_INT(install_signal_handlers); + SET_ITEM_INT(use_hash_seed); + SET_ITEM_UINT(hash_seed); + SET_ITEM_INT(faulthandler); + SET_ITEM_INT(tracemalloc); + SET_ITEM_INT(import_time); + SET_ITEM_INT(show_ref_count); + SET_ITEM_INT(show_alloc_count); + SET_ITEM_INT(dump_refs); + SET_ITEM_INT(malloc_stats); + SET_ITEM_WSTR(filesystem_encoding); + SET_ITEM_WSTR(filesystem_errors); + SET_ITEM_WSTR(pycache_prefix); + SET_ITEM_WSTR(program_name); + SET_ITEM_INT(parse_argv); + SET_ITEM_WSTRLIST(argv); + SET_ITEM_WSTRLIST(xoptions); + SET_ITEM_WSTRLIST(warnoptions); + SET_ITEM_WSTR(pythonpath_env); + SET_ITEM_WSTR(home); + SET_ITEM_WSTRLIST(module_search_paths); + SET_ITEM_WSTR(executable); + SET_ITEM_WSTR(prefix); + SET_ITEM_WSTR(base_prefix); + SET_ITEM_WSTR(exec_prefix); + SET_ITEM_WSTR(base_exec_prefix); + SET_ITEM_INT(site_import); + SET_ITEM_INT(bytes_warning); + SET_ITEM_INT(inspect); + SET_ITEM_INT(interactive); + SET_ITEM_INT(optimization_level); + SET_ITEM_INT(parser_debug); + SET_ITEM_INT(write_bytecode); + SET_ITEM_INT(verbose); + SET_ITEM_INT(quiet); + SET_ITEM_INT(user_site_directory); + SET_ITEM_INT(configure_c_stdio); + SET_ITEM_INT(buffered_stdio); + SET_ITEM_WSTR(stdio_encoding); + SET_ITEM_WSTR(stdio_errors); +#ifdef MS_WINDOWS + SET_ITEM_INT(legacy_windows_stdio); +#endif + SET_ITEM_INT(skip_source_first_line); + SET_ITEM_WSTR(run_command); + SET_ITEM_WSTR(run_module); + SET_ITEM_WSTR(run_filename); + SET_ITEM_INT(_install_importlib); + SET_ITEM_WSTR(check_hash_pycs_mode); + SET_ITEM_INT(pathconfig_warnings); + SET_ITEM_INT(_init_main); + + return dict; + +fail: + Py_DECREF(dict); + return NULL; + +#undef FROM_WSTRING +#undef SET_ITEM +#undef SET_ITEM_INT +#undef SET_ITEM_UINT +#undef SET_ITEM_WSTR +#undef SET_ITEM_WSTRLIST +} + + +static const char* +config_get_env(const PyConfig *config, const char *name) +{ + return _Py_GetEnv(config->use_environment, name); +} + + +/* Get a copy of the environment variable as wchar_t*. + Return 0 on success, but *dest can be NULL. + Return -1 on memory allocation failure. Return -2 on decoding error. */ +static PyStatus +config_get_env_dup(PyConfig *config, + wchar_t **dest, + wchar_t *wname, char *name, + const char *decode_err_msg) +{ + assert(*dest == NULL); + assert(config->use_environment >= 0); + + if (!config->use_environment) { + *dest = NULL; + return _PyStatus_OK(); + } + +#ifdef MS_WINDOWS + const wchar_t *var = _wgetenv(wname); + if (!var || var[0] == '\0') { + *dest = NULL; + return _PyStatus_OK(); + } + + return PyConfig_SetString(config, dest, var); +#else + const char *var = getenv(name); + if (!var || var[0] == '\0') { + *dest = NULL; + return _PyStatus_OK(); + } + + return config_set_bytes_string(config, dest, var, decode_err_msg); +#endif +} + + +#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \ + config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME) + + +static void +config_get_global_vars(PyConfig *config) +{ + if (config->_config_init != _PyConfig_INIT_COMPAT) { + /* Python and Isolated configuration ignore global variables */ + return; + } + +#define COPY_FLAG(ATTR, VALUE) \ + if (config->ATTR == -1) { \ + config->ATTR = VALUE; \ + } +#define COPY_NOT_FLAG(ATTR, VALUE) \ + if (config->ATTR == -1) { \ + config->ATTR = !(VALUE); \ + } + + COPY_FLAG(isolated, Py_IsolatedFlag); + COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); + COPY_FLAG(bytes_warning, Py_BytesWarningFlag); + COPY_FLAG(inspect, Py_InspectFlag); + COPY_FLAG(interactive, Py_InteractiveFlag); + COPY_FLAG(optimization_level, Py_OptimizeFlag); + COPY_FLAG(parser_debug, Py_DebugFlag); + COPY_FLAG(verbose, Py_VerboseFlag); + COPY_FLAG(quiet, Py_QuietFlag); +#ifdef MS_WINDOWS + COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag); +#endif + COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag); + + COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag); + COPY_NOT_FLAG(site_import, Py_NoSiteFlag); + COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag); + COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory); + +#undef COPY_FLAG +#undef COPY_NOT_FLAG +} + + +/* Set Py_xxx global configuration variables from 'config' configuration. */ +static void +config_set_global_vars(const PyConfig *config) +{ +#define COPY_FLAG(ATTR, VAR) \ + if (config->ATTR != -1) { \ + VAR = config->ATTR; \ + } +#define COPY_NOT_FLAG(ATTR, VAR) \ + if (config->ATTR != -1) { \ + VAR = !config->ATTR; \ + } + + COPY_FLAG(isolated, Py_IsolatedFlag); + COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); + COPY_FLAG(bytes_warning, Py_BytesWarningFlag); + COPY_FLAG(inspect, Py_InspectFlag); + COPY_FLAG(interactive, Py_InteractiveFlag); + COPY_FLAG(optimization_level, Py_OptimizeFlag); + COPY_FLAG(parser_debug, Py_DebugFlag); + COPY_FLAG(verbose, Py_VerboseFlag); + COPY_FLAG(quiet, Py_QuietFlag); +#ifdef MS_WINDOWS + COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag); +#endif + COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag); + + COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag); + COPY_NOT_FLAG(site_import, Py_NoSiteFlag); + COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag); + COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory); + + /* Random or non-zero hash seed */ + Py_HashRandomizationFlag = (config->use_hash_seed == 0 || + config->hash_seed != 0); + +#undef COPY_FLAG +#undef COPY_NOT_FLAG +} + + +/* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ + environment variables on macOS if available. */ +static PyStatus +config_init_program_name(PyConfig *config) +{ + PyStatus status; + + /* If Py_SetProgramName() was called, use its value */ + const wchar_t *program_name = _Py_path_config.program_name; + if (program_name != NULL) { + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _PyStatus_NO_MEMORY(); + } + return _PyStatus_OK(); + } + +#ifdef __APPLE__ + /* On MacOS X, when the Python interpreter is embedded in an + application bundle, it gets executed by a bootstrapping script + that does os.execve() with an argv[0] that's different from the + actual Python executable. This is needed to keep the Finder happy, + or rather, to work around Apple's overly strict requirements of + the process name. However, we still need a usable sys.executable, + so the actual executable path is passed in an environment variable. + See Lib/plat-mac/bundlebuiler.py for details about the bootstrap + script. */ + const char *p = config_get_env(config, "PYTHONEXECUTABLE"); + if (p != NULL) { + status = CONFIG_SET_BYTES_STR(config, &config->program_name, p, + "PYTHONEXECUTABLE environment variable"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); + } +#ifdef WITH_NEXT_FRAMEWORK + else { + const char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__"); + if (pyvenv_launcher && *pyvenv_launcher) { + /* Used by Mac/Tools/pythonw.c to forward + * the argv0 of the stub executable + */ + status = CONFIG_SET_BYTES_STR(config, + &config->program_name, + pyvenv_launcher, + "__PYVENV_LAUNCHER__ environment variable"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); + } + } +#endif /* WITH_NEXT_FRAMEWORK */ +#endif /* __APPLE__ */ + + /* Use argv[0] if available and non-empty */ + const PyWideStringList *argv = &config->argv; + if (argv->length >= 1 && argv->items[0][0] != L'\0') { + config->program_name = _PyMem_RawWcsdup(argv->items[0]); + if (config->program_name == NULL) { + return _PyStatus_NO_MEMORY(); + } + return _PyStatus_OK(); + } + + /* Last fall back: hardcoded name */ +#ifdef MS_WINDOWS + const wchar_t *default_program_name = L"python"; +#else + const wchar_t *default_program_name = L"python3"; +#endif + status = PyConfig_SetString(config, &config->program_name, + default_program_name); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); +} + +static PyStatus +config_init_executable(PyConfig *config) +{ + assert(config->executable == NULL); + + /* If Py_SetProgramFullPath() was called, use its value */ + const wchar_t *program_full_path = _Py_path_config.program_full_path; + if (program_full_path != NULL) { + PyStatus status = PyConfig_SetString(config, + &config->executable, + program_full_path); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); + } + return _PyStatus_OK(); +} + + +static const wchar_t* +config_get_xoption(const PyConfig *config, wchar_t *name) +{ + return _Py_get_xoption(&config->xoptions, name); +} + + +static PyStatus +config_init_home(PyConfig *config) +{ + assert(config->home == NULL); + + /* If Py_SetPythonHome() was called, use its value */ + wchar_t *home = _Py_path_config.home; + if (home) { + PyStatus status = PyConfig_SetString(config, &config->home, home); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); + } + + return CONFIG_GET_ENV_DUP(config, &config->home, + L"PYTHONHOME", "PYTHONHOME"); +} + + +static PyStatus +config_init_hash_seed(PyConfig *config) +{ + const char *seed_text = config_get_env(config, "PYTHONHASHSEED"); + + Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc)); + /* Convert a text seed to a numeric one */ + if (seed_text && strcmp(seed_text, "random") != 0) { + const char *endptr = seed_text; + unsigned long seed; + errno = 0; + seed = strtoul(seed_text, (char **)&endptr, 10); + if (*endptr != '\0' + || seed > 4294967295UL + || (errno == ERANGE && seed == ULONG_MAX)) + { + return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" " + "or an integer in range [0; 4294967295]"); + } + /* Use a specific hash */ + config->use_hash_seed = 1; + config->hash_seed = seed; + } + else { + /* Use a random hash */ + config->use_hash_seed = 0; + config->hash_seed = 0; + } + return _PyStatus_OK(); +} + + +static int +config_wstr_to_int(const wchar_t *wstr, int *result) +{ + const wchar_t *endptr = wstr; + errno = 0; + long value = wcstol(wstr, (wchar_t **)&endptr, 10); + if (*endptr != '\0' || errno == ERANGE) { + return -1; + } + if (value < INT_MIN || value > INT_MAX) { + return -1; + } + + *result = (int)value; + return 0; +} + + +static PyStatus +config_read_env_vars(PyConfig *config) +{ + PyStatus status; + int use_env = config->use_environment; + + /* Get environment variables */ + _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG"); + _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE"); + _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE"); + _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT"); + + int dont_write_bytecode = 0; + _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); + if (dont_write_bytecode) { + config->write_bytecode = 0; + } + + int no_user_site_directory = 0; + _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE"); + if (no_user_site_directory) { + config->user_site_directory = 0; + } + + int unbuffered_stdio = 0; + _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED"); + if (unbuffered_stdio) { + config->buffered_stdio = 0; + } + +#ifdef MS_WINDOWS + _Py_get_env_flag(use_env, &config->legacy_windows_stdio, + "PYTHONLEGACYWINDOWSSTDIO"); +#endif + + if (config_get_env(config, "PYTHONDUMPREFS")) { + config->dump_refs = 1; + } + if (config_get_env(config, "PYTHONMALLOCSTATS")) { + config->malloc_stats = 1; + } + + if (config->pythonpath_env == NULL) { + status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env, + L"PYTHONPATH", "PYTHONPATH"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->use_hash_seed < 0) { + status = config_init_hash_seed(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + return _PyStatus_OK(); +} + + +static PyStatus +config_init_tracemalloc(PyConfig *config) +{ + int nframe; + int valid; + + const char *env = config_get_env(config, "PYTHONTRACEMALLOC"); + if (env) { + if (!_Py_str_to_int(env, &nframe)) { + valid = (nframe >= 0); + } + else { + valid = 0; + } + if (!valid) { + return _PyStatus_ERR("PYTHONTRACEMALLOC: invalid number of frames"); + } + config->tracemalloc = nframe; + } + + const wchar_t *xoption = config_get_xoption(config, L"tracemalloc"); + if (xoption) { + const wchar_t *sep = wcschr(xoption, L'='); + if (sep) { + if (!config_wstr_to_int(sep + 1, &nframe)) { + valid = (nframe >= 0); + } + else { + valid = 0; + } + if (!valid) { + return _PyStatus_ERR("-X tracemalloc=NFRAME: " + "invalid number of frames"); + } + } + else { + /* -X tracemalloc behaves as -X tracemalloc=1 */ + nframe = 1; + } + config->tracemalloc = nframe; + } + return _PyStatus_OK(); +} + + +static PyStatus +config_init_pycache_prefix(PyConfig *config) +{ + assert(config->pycache_prefix == NULL); + + const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix"); + if (xoption) { + const wchar_t *sep = wcschr(xoption, L'='); + if (sep && wcslen(sep) > 1) { + config->pycache_prefix = _PyMem_RawWcsdup(sep + 1); + if (config->pycache_prefix == NULL) { + return _PyStatus_NO_MEMORY(); + } + } + else { + // PYTHONPYCACHEPREFIX env var ignored + // if "-X pycache_prefix=" option is used + config->pycache_prefix = NULL; + } + return _PyStatus_OK(); + } + + return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix, + L"PYTHONPYCACHEPREFIX", + "PYTHONPYCACHEPREFIX"); +} + + +static PyStatus +config_read_complex_options(PyConfig *config) +{ + /* More complex options configured by env var and -X option */ + if (config->faulthandler < 0) { + if (config_get_env(config, "PYTHONFAULTHANDLER") + || config_get_xoption(config, L"faulthandler")) { + config->faulthandler = 1; + } + } + if (config_get_env(config, "PYTHONPROFILEIMPORTTIME") + || config_get_xoption(config, L"importtime")) { + config->import_time = 1; + } + + PyStatus status; + if (config->tracemalloc < 0) { + status = config_init_tracemalloc(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->pycache_prefix == NULL) { + status = config_init_pycache_prefix(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + return _PyStatus_OK(); +} + + +static const wchar_t * +config_get_stdio_errors(const PyConfig *config) +{ +#ifndef MS_WINDOWS + const char *loc = setlocale(LC_CTYPE, NULL); + if (loc != NULL) { + /* surrogateescape is the default in the legacy C and POSIX locales */ + if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) { + return L"surrogateescape"; + } + +#ifdef PY_COERCE_C_LOCALE + /* surrogateescape is the default in locale coercion target locales */ + if (_Py_IsLocaleCoercionTarget(loc)) { + return L"surrogateescape"; + } +#endif + } + + return L"strict"; +#else + /* On Windows, always use surrogateescape by default */ + return L"surrogateescape"; +#endif +} + + +static PyStatus +config_get_locale_encoding(PyConfig *config, wchar_t **locale_encoding) +{ +#ifdef MS_WINDOWS + char encoding[20]; + PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); + return PyConfig_SetBytesString(config, locale_encoding, encoding); +#elif defined(_Py_FORCE_UTF8_LOCALE) + return PyConfig_SetString(config, locale_encoding, L"utf-8"); +#else + const char *encoding = nl_langinfo(CODESET); + if (!encoding || encoding[0] == '\0') { + return _PyStatus_ERR("failed to get the locale encoding: " + "nl_langinfo(CODESET) failed"); + } + /* nl_langinfo(CODESET) is decoded by Py_DecodeLocale() */ + return CONFIG_SET_BYTES_STR(config, + locale_encoding, encoding, + "nl_langinfo(CODESET)"); +#endif +} + + +static PyStatus +config_init_stdio_encoding(PyConfig *config, + const PyPreConfig *preconfig) +{ + PyStatus status; + + /* If Py_SetStandardStreamEncoding() have been called, use these + parameters. */ + if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) { + status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding, + _Py_StandardStreamEncoding, + "_Py_StandardStreamEncoding"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) { + status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors, + _Py_StandardStreamErrors, + "_Py_StandardStreamErrors"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->stdio_encoding != NULL && config->stdio_errors != NULL) { + return _PyStatus_OK(); + } + + /* PYTHONIOENCODING environment variable */ + const char *opt = config_get_env(config, "PYTHONIOENCODING"); + if (opt) { + char *pythonioencoding = _PyMem_RawStrdup(opt); + if (pythonioencoding == NULL) { + return _PyStatus_NO_MEMORY(); + } + + char *errors = strchr(pythonioencoding, ':'); + if (errors) { + *errors = '\0'; + errors++; + if (!errors[0]) { + errors = NULL; + } + } + + /* Does PYTHONIOENCODING contain an encoding? */ + if (pythonioencoding[0]) { + if (config->stdio_encoding == NULL) { + status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding, + pythonioencoding, + "PYTHONIOENCODING environment variable"); + if (_PyStatus_EXCEPTION(status)) { + PyMem_RawFree(pythonioencoding); + return status; + } + } + + /* If the encoding is set but not the error handler, + use "strict" error handler by default. + PYTHONIOENCODING=latin1 behaves as + PYTHONIOENCODING=latin1:strict. */ + if (!errors) { + errors = "strict"; + } + } + + if (config->stdio_errors == NULL && errors != NULL) { + status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors, + errors, + "PYTHONIOENCODING environment variable"); + if (_PyStatus_EXCEPTION(status)) { + PyMem_RawFree(pythonioencoding); + return status; + } + } + + PyMem_RawFree(pythonioencoding); + } + + /* UTF-8 Mode uses UTF-8/surrogateescape */ + if (preconfig->utf8_mode) { + if (config->stdio_encoding == NULL) { + status = PyConfig_SetString(config, &config->stdio_encoding, + L"utf-8"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + if (config->stdio_errors == NULL) { + status = PyConfig_SetString(config, &config->stdio_errors, + L"surrogateescape"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + } + + /* Choose the default error handler based on the current locale. */ + if (config->stdio_encoding == NULL) { + status = config_get_locale_encoding(config, &config->stdio_encoding); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + if (config->stdio_errors == NULL) { + const wchar_t *errors = config_get_stdio_errors(config); + assert(errors != NULL); + + status = PyConfig_SetString(config, &config->stdio_errors, errors); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + return _PyStatus_OK(); +} + + +static PyStatus +config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig) +{ + PyStatus status; + + if (config->filesystem_encoding == NULL) { +#ifdef _Py_FORCE_UTF8_FS_ENCODING + status = PyConfig_SetString(config, &config->filesystem_encoding, L"utf-8"); +#else + +#ifdef MS_WINDOWS + if (preconfig->legacy_windows_fs_encoding) { + /* Legacy Windows filesystem encoding: mbcs/replace */ + status = PyConfig_SetString(config, &config->filesystem_encoding, + L"mbcs"); + } + else +#endif + if (preconfig->utf8_mode) { + status = PyConfig_SetString(config, &config->filesystem_encoding, + L"utf-8"); + } +#ifndef MS_WINDOWS + else if (_Py_GetForceASCII()) { + status = PyConfig_SetString(config, &config->filesystem_encoding, + L"ascii"); + } +#endif + else { +#ifdef MS_WINDOWS + /* Windows defaults to utf-8/surrogatepass (PEP 529). */ + status = PyConfig_SetString(config, &config->filesystem_encoding, + L"utf-8"); +#else + status = config_get_locale_encoding(config, + &config->filesystem_encoding); +#endif + } +#endif /* !_Py_FORCE_UTF8_FS_ENCODING */ + + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->filesystem_errors == NULL) { + const wchar_t *errors; +#ifdef MS_WINDOWS + if (preconfig->legacy_windows_fs_encoding) { + errors = L"replace"; + } + else { + errors = L"surrogatepass"; + } +#else + errors = L"surrogateescape"; +#endif + status = PyConfig_SetString(config, &config->filesystem_errors, errors); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + return _PyStatus_OK(); +} + + +static PyStatus +config_read(PyConfig *config) +{ + PyStatus status; + const PyPreConfig *preconfig = &_PyRuntime.preconfig; + + if (config->use_environment) { + status = config_read_env_vars(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + /* -X options */ + if (config_get_xoption(config, L"showrefcount")) { + config->show_ref_count = 1; + } + if (config_get_xoption(config, L"showalloccount")) { + config->show_alloc_count = 1; + } + + status = config_read_complex_options(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + if (config->home == NULL) { + status = config_init_home(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->executable == NULL) { + status = config_init_executable(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->_install_importlib) { + status = _PyConfig_InitPathConfig(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + /* default values */ + if (config->dev_mode) { + if (config->faulthandler < 0) { + config->faulthandler = 1; + } + } + if (config->faulthandler < 0) { + config->faulthandler = 0; + } + if (config->tracemalloc < 0) { + config->tracemalloc = 0; + } + if (config->use_hash_seed < 0) { + config->use_hash_seed = 0; + config->hash_seed = 0; + } + + if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) { + status = config_init_fs_encoding(config, preconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + status = config_init_stdio_encoding(config, preconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + if (config->argv.length < 1) { + /* Ensure at least one (empty) argument is seen */ + status = PyWideStringList_Append(&config->argv, L""); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->check_hash_pycs_mode == NULL) { + status = PyConfig_SetString(config, &config->check_hash_pycs_mode, + L"default"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->configure_c_stdio < 0) { + config->configure_c_stdio = 1; + } + + return _PyStatus_OK(); +} + + +static void +config_init_stdio(const PyConfig *config) +{ +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + /* don't translate newlines (\r\n <=> \n) */ + _setmode(fileno(stdin), O_BINARY); + _setmode(fileno(stdout), O_BINARY); + _setmode(fileno(stderr), O_BINARY); +#endif + + if (!config->buffered_stdio) { +#ifdef HAVE_SETVBUF + setvbuf(stdin, (char *)NULL, _IONBF, BUFSIZ); + setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ); + setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ); +#else /* !HAVE_SETVBUF */ + setbuf(stdin, (char *)NULL); + setbuf(stdout, (char *)NULL); + setbuf(stderr, (char *)NULL); +#endif /* !HAVE_SETVBUF */ + } + else if (config->interactive) { +#ifdef MS_WINDOWS + /* Doesn't have to have line-buffered -- use unbuffered */ + /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */ + setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ); +#else /* !MS_WINDOWS */ +#ifdef HAVE_SETVBUF + setvbuf(stdin, (char *)NULL, _IOLBF, BUFSIZ); + setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ); +#endif /* HAVE_SETVBUF */ +#endif /* !MS_WINDOWS */ + /* Leave stderr alone - it should be unbuffered anyway. */ + } +} + + +/* Write the configuration: + + - set Py_xxx global configuration variables + - initialize C standard streams (stdin, stdout, stderr) */ +void +_PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime) +{ + config_set_global_vars(config); + + if (config->configure_c_stdio) { + config_init_stdio(config); + } + + /* Write the new pre-configuration into _PyRuntime */ + PyPreConfig *preconfig = &runtime->preconfig; + preconfig->isolated = config->isolated; + preconfig->use_environment = config->use_environment; + preconfig->dev_mode = config->dev_mode; +} + + +/* --- PyConfig command line parser -------------------------- */ + +static void +config_usage(int error, const wchar_t* program) +{ + FILE *f = error ? stderr : stdout; + + fprintf(f, usage_line, program); + if (error) + fprintf(f, "Try `python -h' for more information.\n"); + else { + fputs(usage_1, f); + fputs(usage_2, f); + fputs(usage_3, f); + fprintf(f, usage_4, (wint_t)DELIM); + fprintf(f, usage_5, (wint_t)DELIM, PYTHONHOMEHELP); + fputs(usage_6, f); + } +} + + +/* Parse the command line arguments */ +static PyStatus +config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions, + Py_ssize_t *opt_index) +{ + PyStatus status; + const PyWideStringList *argv = &config->argv; + int print_version = 0; + const wchar_t* program = config->program_name; + + _PyOS_ResetGetOpt(); + do { + int longindex = -1; + int c = _PyOS_GetOpt(argv->length, argv->items, &longindex); + if (c == EOF) { + break; + } + + if (c == 'c') { + if (config->run_command == NULL) { + /* -c is the last option; following arguments + that look like options are left for the + command to interpret. */ + size_t len = wcslen(_PyOS_optarg) + 1 + 1; + wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len); + if (command == NULL) { + return _PyStatus_NO_MEMORY(); + } + memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t)); + command[len - 2] = '\n'; + command[len - 1] = 0; + config->run_command = command; + } + break; + } + + if (c == 'm') { + /* -m is the last option; following arguments + that look like options are left for the + module to interpret. */ + if (config->run_module == NULL) { + config->run_module = _PyMem_RawWcsdup(_PyOS_optarg); + if (config->run_module == NULL) { + return _PyStatus_NO_MEMORY(); + } + } + break; + } + + switch (c) { + case 0: + // Handle long option. + assert(longindex == 0); // Only one long option now. + if (wcscmp(_PyOS_optarg, L"always") == 0 + || wcscmp(_PyOS_optarg, L"never") == 0 + || wcscmp(_PyOS_optarg, L"default") == 0) + { + status = PyConfig_SetString(config, &config->check_hash_pycs_mode, + _PyOS_optarg); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } else { + fprintf(stderr, "--check-hash-based-pycs must be one of " + "'default', 'always', or 'never'\n"); + config_usage(1, program); + return _PyStatus_EXIT(2); + } + break; + + case 'b': + config->bytes_warning++; + break; + + case 'd': + config->parser_debug++; + break; + + case 'i': + config->inspect++; + config->interactive++; + break; + + case 'E': + case 'I': + case 'X': + /* option handled by _PyPreCmdline_Read() */ + break; + + /* case 'J': reserved for Jython */ + + case 'O': + config->optimization_level++; + break; + + case 'B': + config->write_bytecode = 0; + break; + + case 's': + config->user_site_directory = 0; + break; + + case 'S': + config->site_import = 0; + break; + + case 't': + /* ignored for backwards compatibility */ + break; + + case 'u': + config->buffered_stdio = 0; + break; + + case 'v': + config->verbose++; + break; + + case 'x': + config->skip_source_first_line = 1; + break; + + case 'h': + case '?': + config_usage(0, program); + return _PyStatus_EXIT(0); + + case 'V': + print_version++; + break; + + case 'W': + status = PyWideStringList_Append(warnoptions, _PyOS_optarg); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + break; + + case 'q': + config->quiet++; + break; + + case 'R': + config->use_hash_seed = 0; + break; + + /* This space reserved for other options */ + + default: + /* unknown argument: parsing failed */ + config_usage(1, program); + return _PyStatus_EXIT(2); + } + } while (1); + + if (print_version) { + printf("Python %s\n", + (print_version >= 2) ? Py_GetVersion() : PY_VERSION); + return _PyStatus_EXIT(0); + } + + if (config->run_command == NULL && config->run_module == NULL + && _PyOS_optind < argv->length + && wcscmp(argv->items[_PyOS_optind], L"-") != 0 + && config->run_filename == NULL) + { + config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]); + if (config->run_filename == NULL) { + return _PyStatus_NO_MEMORY(); + } + } + + if (config->run_command != NULL || config->run_module != NULL) { + /* Backup _PyOS_optind */ + _PyOS_optind--; + } + + *opt_index = _PyOS_optind; + + return _PyStatus_OK(); +} + + +#ifdef MS_WINDOWS +# define WCSTOK wcstok_s +#else +# define WCSTOK wcstok +#endif + +/* Get warning options from PYTHONWARNINGS environment variable. */ +static PyStatus +config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions) +{ + PyStatus status; + /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */ + wchar_t *env = NULL; + status = CONFIG_GET_ENV_DUP(config, &env, + L"PYTHONWARNINGS", "PYTHONWARNINGS"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + /* env var is not set or is empty */ + if (env == NULL) { + return _PyStatus_OK(); + } + + + wchar_t *warning, *context = NULL; + for (warning = WCSTOK(env, L",", &context); + warning != NULL; + warning = WCSTOK(NULL, L",", &context)) + { + status = PyWideStringList_Append(warnoptions, warning); + if (_PyStatus_EXCEPTION(status)) { + PyMem_RawFree(env); + return status; + } + } + PyMem_RawFree(env); + return _PyStatus_OK(); +} + + +static PyStatus +config_add_warnoption(PyConfig *config, const wchar_t *option) +{ + if (_PyWideStringList_Find(&config->warnoptions, option)) { + /* Already present: do nothing */ + return _PyStatus_OK(); + } + return PyWideStringList_Append(&config->warnoptions, option); +} + + +static PyStatus +config_init_warnoptions(PyConfig *config, + const PyWideStringList *cmdline_warnoptions, + const PyWideStringList *env_warnoptions) +{ + PyStatus status; + + /* The priority order for warnings configuration is (highest precedence + * first): + * + * - the BytesWarning filter, if needed ('-b', '-bb') + * - any '-W' command line options; then + * - the 'PYTHONWARNINGS' environment variable; then + * - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then + * - any implicit filters added by _warnings.c/warnings.py + * + * All settings except the last are passed to the warnings module via + * the `sys.warnoptions` list. Since the warnings module works on the basis + * of "the most recently added filter will be checked first", we add + * the lowest precedence entries first so that later entries override them. + */ + + if (config->dev_mode) { + status = config_add_warnoption(config, L"default"); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + Py_ssize_t i; + const PyWideStringList *options; + + options = env_warnoptions; + for (i = 0; i < options->length; i++) { + status = config_add_warnoption(config, options->items[i]); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + options = cmdline_warnoptions; + for (i = 0; i < options->length; i++) { + status = config_add_warnoption(config, options->items[i]); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c + * don't even try to emit a warning, so we skip setting the filter in that + * case. + */ + if (config->bytes_warning) { + const wchar_t *filter; + if (config->bytes_warning> 1) { + filter = L"error::BytesWarning"; + } + else { + filter = L"default::BytesWarning"; + } + status = config_add_warnoption(config, filter); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + return _PyStatus_OK(); +} + + +static PyStatus +config_update_argv(PyConfig *config, Py_ssize_t opt_index) +{ + const PyWideStringList *cmdline_argv = &config->argv; + PyWideStringList config_argv = PyWideStringList_INIT; + + /* Copy argv to be able to modify it (to force -c/-m) */ + if (cmdline_argv->length <= opt_index) { + /* Ensure at least one (empty) argument is seen */ + PyStatus status = PyWideStringList_Append(&config_argv, L""); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + else { + PyWideStringList slice; + slice.length = cmdline_argv->length - opt_index; + slice.items = &cmdline_argv->items[opt_index]; + if (_PyWideStringList_Copy(&config_argv, &slice) < 0) { + return _PyStatus_NO_MEMORY(); + } + } + assert(config_argv.length >= 1); + + wchar_t *arg0 = NULL; + if (config->run_command != NULL) { + /* Force sys.argv[0] = '-c' */ + arg0 = L"-c"; + } + else if (config->run_module != NULL) { + /* Force sys.argv[0] = '-m'*/ + arg0 = L"-m"; + } + if (arg0 != NULL) { + arg0 = _PyMem_RawWcsdup(arg0); + if (arg0 == NULL) { + _PyWideStringList_Clear(&config_argv); + return _PyStatus_NO_MEMORY(); + } + + PyMem_RawFree(config_argv.items[0]); + config_argv.items[0] = arg0; + } + + _PyWideStringList_Clear(&config->argv); + config->argv = config_argv; + return _PyStatus_OK(); +} + + +static PyStatus +core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline) +{ + PyStatus status; + + if (config->parse_argv) { + if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) { + return _PyStatus_NO_MEMORY(); + } + } + + PyPreConfig preconfig; + _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig); + + _PyPreConfig_GetConfig(&preconfig, config); + + status = _PyPreCmdline_Read(precmdline, &preconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = _PyPreCmdline_SetConfig(precmdline, config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); +} + + +static PyStatus +config_read_cmdline(PyConfig *config) +{ + PyStatus status; + PyWideStringList cmdline_warnoptions = PyWideStringList_INIT; + PyWideStringList env_warnoptions = PyWideStringList_INIT; + + if (config->parse_argv < 0) { + config->parse_argv = 1; + } + + if (config->program_name == NULL) { + status = config_init_program_name(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (config->parse_argv) { + Py_ssize_t opt_index; + status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + + status = config_update_argv(config, opt_index); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + } + + if (config->use_environment) { + status = config_init_env_warnoptions(config, &env_warnoptions); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + } + + status = config_init_warnoptions(config, + &cmdline_warnoptions, &env_warnoptions); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + + status = _PyStatus_OK(); + +done: + _PyWideStringList_Clear(&cmdline_warnoptions); + _PyWideStringList_Clear(&env_warnoptions); + return status; +} + + +PyStatus +_PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args) +{ + PyStatus status = _Py_PreInitializeFromConfig(config, args); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + return _PyArgv_AsWstrList(args, &config->argv); +} + + +/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python + if needed to ensure that encodings are properly configured. */ +PyStatus +PyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv) +{ + _PyArgv args = { + .argc = argc, + .use_bytes_argv = 1, + .bytes_argv = argv, + .wchar_argv = NULL}; + return _PyConfig_SetPyArgv(config, &args); +} + + +PyStatus +PyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv) +{ + _PyArgv args = { + .argc = argc, + .use_bytes_argv = 0, + .bytes_argv = NULL, + .wchar_argv = argv}; + return _PyConfig_SetPyArgv(config, &args); +} + + +/* Read the configuration into PyConfig from: + + * Command line arguments + * Environment variables + * Py_xxx global configuration variables + + The only side effects are to modify config and to call _Py_SetArgcArgv(). */ +PyStatus +PyConfig_Read(PyConfig *config) +{ + PyStatus status; + PyWideStringList orig_argv = PyWideStringList_INIT; + + status = _Py_PreInitializeFromConfig(config, NULL); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + config_get_global_vars(config); + + if (_PyWideStringList_Copy(&orig_argv, &config->argv) < 0) { + return _PyStatus_NO_MEMORY(); + } + + _PyPreCmdline precmdline = _PyPreCmdline_INIT; + status = core_read_precmdline(config, &precmdline); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + + assert(config->isolated >= 0); + if (config->isolated) { + config->use_environment = 0; + config->user_site_directory = 0; + } + + status = config_read_cmdline(config); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + + status = config_read(config); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + + if (_Py_SetArgcArgv(orig_argv.length, orig_argv.items) < 0) { + status = _PyStatus_NO_MEMORY(); + goto done; + } + + /* Check config consistency */ + assert(config->isolated >= 0); + assert(config->use_environment >= 0); + assert(config->dev_mode >= 0); + assert(config->install_signal_handlers >= 0); + assert(config->use_hash_seed >= 0); + assert(config->faulthandler >= 0); + assert(config->tracemalloc >= 0); + assert(config->site_import >= 0); + assert(config->bytes_warning >= 0); + assert(config->inspect >= 0); + assert(config->interactive >= 0); + assert(config->optimization_level >= 0); + assert(config->parser_debug >= 0); + assert(config->write_bytecode >= 0); + assert(config->verbose >= 0); + assert(config->quiet >= 0); + assert(config->user_site_directory >= 0); + assert(config->parse_argv >= 0); + assert(config->configure_c_stdio >= 0); + assert(config->buffered_stdio >= 0); + assert(config->program_name != NULL); + assert(_PyWideStringList_CheckConsistency(&config->argv)); + /* sys.argv must be non-empty: empty argv is replaced with [''] */ + assert(config->argv.length >= 1); + assert(_PyWideStringList_CheckConsistency(&config->xoptions)); + assert(_PyWideStringList_CheckConsistency(&config->warnoptions)); + assert(_PyWideStringList_CheckConsistency(&config->module_search_paths)); + if (config->_install_importlib) { + assert(config->module_search_paths_set != 0); + /* don't check config->module_search_paths */ + assert(config->executable != NULL); + assert(config->prefix != NULL); + assert(config->base_prefix != NULL); + assert(config->exec_prefix != NULL); + assert(config->base_exec_prefix != NULL); + } + assert(config->filesystem_encoding != NULL); + assert(config->filesystem_errors != NULL); + assert(config->stdio_encoding != NULL); + assert(config->stdio_errors != NULL); +#ifdef MS_WINDOWS + assert(config->legacy_windows_stdio >= 0); +#endif + /* -c and -m options are exclusive */ + assert(!(config->run_command != NULL && config->run_module != NULL)); + assert(config->check_hash_pycs_mode != NULL); + assert(config->_install_importlib >= 0); + assert(config->pathconfig_warnings >= 0); + + status = _PyStatus_OK(); + +done: + _PyWideStringList_Clear(&orig_argv); + _PyPreCmdline_Clear(&precmdline); + return status; +} + + +PyObject* +_Py_GetConfigsAsDict(void) +{ + PyObject *result = NULL; + PyObject *dict = NULL; + + result = PyDict_New(); + if (result == NULL) { + goto error; + } + + /* global result */ + dict = _Py_GetGlobalVariablesAsDict(); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(result, "global_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + /* pre config */ + PyInterpreterState *interp = _PyInterpreterState_Get(); + const PyPreConfig *pre_config = &_PyRuntime.preconfig; + dict = _PyPreConfig_AsDict(pre_config); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(result, "pre_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + /* core config */ + const PyConfig *config = &interp->config; + dict = config_as_dict(config); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(result, "config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + return result; + +error: + Py_XDECREF(result); + Py_XDECREF(dict); + return NULL; +} diff --git a/Python/pathconfig.c b/Python/pathconfig.c index bbf29b2..ec67405 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -2,7 +2,7 @@ #include "Python.h" #include "osdefs.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_fileutils.h" #include "pycore_pathconfig.h" #include "pycore_pymem.h" @@ -34,7 +34,7 @@ copy_wstr(wchar_t **dst, const wchar_t *src) static void -_PyPathConfig_Clear(_PyPathConfig *config) +pathconfig_clear(_PyPathConfig *config) { /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator, since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be @@ -63,12 +63,11 @@ _PyPathConfig_Clear(_PyPathConfig *config) } -/* Calculate the path configuration: initialize path_config from core_config */ -static _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *path_config, - const _PyCoreConfig *core_config) +/* Calculate the path configuration: initialize pathconfig from config */ +static PyStatus +pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config) { - _PyInitError err; + PyStatus status; _PyPathConfig new_config = _PyPathConfig_INIT; PyMemAllocatorEx old_alloc; @@ -76,40 +75,40 @@ _PyPathConfig_Calculate(_PyPathConfig *path_config, /* Calculate program_full_path, prefix, exec_prefix, dll_path (Windows), and module_search_path */ - err = _PyPathConfig_Calculate_impl(&new_config, core_config); - if (_Py_INIT_FAILED(err)) { - goto err; + status = _PyPathConfig_Calculate(&new_config, config); + if (_PyStatus_EXCEPTION(status)) { + goto error; } - /* Copy home and program_name from core_config */ - if (copy_wstr(&new_config.home, core_config->home) < 0) { - err = _Py_INIT_NO_MEMORY(); - goto err; + /* Copy home and program_name from config */ + if (copy_wstr(&new_config.home, config->home) < 0) { + status = _PyStatus_NO_MEMORY(); + goto error; } - if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) { - err = _Py_INIT_NO_MEMORY(); - goto err; + if (copy_wstr(&new_config.program_name, config->program_name) < 0) { + status = _PyStatus_NO_MEMORY(); + goto error; } - _PyPathConfig_Clear(path_config); - *path_config = new_config; + pathconfig_clear(pathconfig); + *pathconfig = new_config; - err = _Py_INIT_OK(); + status = _PyStatus_OK(); goto done; -err: - _PyPathConfig_Clear(&new_config); +error: + pathconfig_clear(&new_config); done: PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return err; + return status; } -_PyInitError +PyStatus _PyPathConfig_SetGlobal(const _PyPathConfig *config) { - _PyInitError err; + PyStatus status; _PyPathConfig new_config = _PyPathConfig_INIT; PyMemAllocatorEx old_alloc; @@ -118,8 +117,8 @@ _PyPathConfig_SetGlobal(const _PyPathConfig *config) #define COPY_ATTR(ATTR) \ do { \ if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \ - _PyPathConfig_Clear(&new_config); \ - err = _Py_INIT_NO_MEMORY(); \ + pathconfig_clear(&new_config); \ + status = _PyStatus_NO_MEMORY(); \ goto done; \ } \ } while (0) @@ -134,15 +133,15 @@ _PyPathConfig_SetGlobal(const _PyPathConfig *config) COPY_ATTR(program_name); COPY_ATTR(home); - _PyPathConfig_Clear(&_Py_path_config); + pathconfig_clear(&_Py_path_config); /* Steal new_config strings; don't clear new_config */ _Py_path_config = new_config; - err = _Py_INIT_OK(); + status = _PyStatus_OK(); done: PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return err; + return status; } @@ -152,14 +151,14 @@ _PyPathConfig_ClearGlobal(void) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyPathConfig_Clear(&_Py_path_config); + pathconfig_clear(&_Py_path_config); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } static wchar_t* -_PyWstrList_Join(const _PyWstrList *list, wchar_t sep) +_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep) { size_t len = 1; /* NUL terminator */ for (Py_ssize_t i=0; i < list->length; i++) { @@ -189,70 +188,69 @@ _PyWstrList_Join(const _PyWstrList *list, wchar_t sep) } -/* Set the global path configuration from core_config. */ -_PyInitError -_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config) +/* Set the global path configuration from config. */ +PyStatus +_PyConfig_SetPathConfig(const PyConfig *config) { PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyInitError err; - _PyPathConfig path_config = _PyPathConfig_INIT; + PyStatus status; + _PyPathConfig pathconfig = _PyPathConfig_INIT; - path_config.module_search_path = _PyWstrList_Join(&core_config->module_search_paths, DELIM); - if (path_config.module_search_path == NULL) { + pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); + if (pathconfig.module_search_path == NULL) { goto no_memory; } - if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) { + if (copy_wstr(&pathconfig.program_full_path, config->executable) < 0) { goto no_memory; } - if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) { + if (copy_wstr(&pathconfig.prefix, config->prefix) < 0) { goto no_memory; } - if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) { + if (copy_wstr(&pathconfig.exec_prefix, config->exec_prefix) < 0) { goto no_memory; } #ifdef MS_WINDOWS - path_config.dll_path = _Py_GetDLLPath(); - if (path_config.dll_path == NULL) { + pathconfig.dll_path = _Py_GetDLLPath(); + if (pathconfig.dll_path == NULL) { goto no_memory; } #endif - if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) { + if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) { goto no_memory; } - if (copy_wstr(&path_config.home, core_config->home) < 0) { + if (copy_wstr(&pathconfig.home, config->home) < 0) { goto no_memory; } - err = _PyPathConfig_SetGlobal(&path_config); - if (_Py_INIT_FAILED(err)) { + status = _PyPathConfig_SetGlobal(&pathconfig); + if (_PyStatus_EXCEPTION(status)) { goto done; } - err = _Py_INIT_OK(); + status = _PyStatus_OK(); goto done; no_memory: - err = _Py_INIT_NO_MEMORY(); + status = _PyStatus_NO_MEMORY(); done: - _PyPathConfig_Clear(&path_config); + pathconfig_clear(&pathconfig); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return err; + return status; } -static _PyInitError -core_config_init_module_search_paths(_PyCoreConfig *config, - _PyPathConfig *path_config) +static PyStatus +config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig) { - assert(!config->use_module_search_paths); + assert(!config->module_search_paths_set); - _PyWstrList_Clear(&config->module_search_paths); + _PyWideStringList_Clear(&config->module_search_paths); - const wchar_t *sys_path = path_config->module_search_path; + const wchar_t *sys_path = pathconfig->module_search_path; const wchar_t delim = DELIM; const wchar_t *p = sys_path; while (1) { @@ -264,15 +262,15 @@ core_config_init_module_search_paths(_PyCoreConfig *config, size_t path_len = (p - sys_path); wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t)); if (path == NULL) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } memcpy(path, sys_path, path_len * sizeof(wchar_t)); path[path_len] = L'\0'; - int res = _PyWstrList_Append(&config->module_search_paths, path); + PyStatus status = PyWideStringList_Append(&config->module_search_paths, path); PyMem_RawFree(path); - if (res < 0) { - return _Py_INIT_NO_MEMORY(); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (*p == '\0') { @@ -280,96 +278,96 @@ core_config_init_module_search_paths(_PyCoreConfig *config, } sys_path = p + 1; } - config->use_module_search_paths = 1; - return _Py_INIT_OK(); + config->module_search_paths_set = 1; + return _PyStatus_OK(); } -static _PyInitError -_PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config) +static PyStatus +config_calculate_pathconfig(PyConfig *config) { - _PyPathConfig path_config = _PyPathConfig_INIT; - _PyInitError err; + _PyPathConfig pathconfig = _PyPathConfig_INIT; + PyStatus status; - err = _PyPathConfig_Calculate(&path_config, config); - if (_Py_INIT_FAILED(err)) { + status = pathconfig_calculate(&pathconfig, config); + if (_PyStatus_EXCEPTION(status)) { goto error; } - if (!config->use_module_search_paths) { - err = core_config_init_module_search_paths(config, &path_config); - if (_Py_INIT_FAILED(err)) { + if (!config->module_search_paths_set) { + status = config_init_module_search_paths(config, &pathconfig); + if (_PyStatus_EXCEPTION(status)) { goto error; } } if (config->executable == NULL) { if (copy_wstr(&config->executable, - path_config.program_full_path) < 0) { + pathconfig.program_full_path) < 0) { goto no_memory; } } if (config->prefix == NULL) { - if (copy_wstr(&config->prefix, path_config.prefix) < 0) { + if (copy_wstr(&config->prefix, pathconfig.prefix) < 0) { goto no_memory; } } if (config->exec_prefix == NULL) { if (copy_wstr(&config->exec_prefix, - path_config.exec_prefix) < 0) { + pathconfig.exec_prefix) < 0) { goto no_memory; } } - if (path_config.isolated != -1) { - config->isolated = path_config.isolated; + if (pathconfig.isolated != -1) { + config->isolated = pathconfig.isolated; } - if (path_config.site_import != -1) { - config->site_import = path_config.site_import; + if (pathconfig.site_import != -1) { + config->site_import = pathconfig.site_import; } - _PyPathConfig_Clear(&path_config); - return _Py_INIT_OK(); + pathconfig_clear(&pathconfig); + return _PyStatus_OK(); no_memory: - err = _Py_INIT_NO_MEMORY(); + status = _PyStatus_NO_MEMORY(); error: - _PyPathConfig_Clear(&path_config); - return err; + pathconfig_clear(&pathconfig); + return status; } -_PyInitError -_PyCoreConfig_InitPathConfig(_PyCoreConfig *config) +PyStatus +_PyConfig_InitPathConfig(PyConfig *config) { /* Do we need to calculate the path? */ - if (!config->use_module_search_paths + if (!config->module_search_paths_set || (config->executable == NULL) || (config->prefix == NULL) || (config->exec_prefix == NULL)) { - _PyInitError err = _PyCoreConfig_CalculatePathConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = config_calculate_pathconfig(config); + if (_PyStatus_EXCEPTION(status)) { + return status; } } if (config->base_prefix == NULL) { if (copy_wstr(&config->base_prefix, config->prefix) < 0) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } } if (config->base_exec_prefix == NULL) { if (copy_wstr(&config->base_exec_prefix, config->exec_prefix) < 0) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -381,26 +379,26 @@ pathconfig_global_init(void) return; } - _PyInitError err; - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + PyStatus status; + PyConfig config; + _PyConfig_InitCompatConfig(&config); - err = _PyCoreConfig_Read(&config); - if (_Py_INIT_FAILED(err)) { + status = PyConfig_Read(&config); + if (_PyStatus_EXCEPTION(status)) { goto error; } - err = _PyCoreConfig_SetPathConfig(&config); - if (_Py_INIT_FAILED(err)) { + status = _PyConfig_SetPathConfig(&config); + if (_PyStatus_EXCEPTION(status)) { goto error; } - _PyCoreConfig_Clear(&config); + PyConfig_Clear(&config); return; error: - _PyCoreConfig_Clear(&config); - _Py_ExitInitError(err); + PyConfig_Clear(&config); + Py_ExitStatusException(status); } @@ -410,7 +408,7 @@ void Py_SetPath(const wchar_t *path) { if (path == NULL) { - _PyPathConfig_Clear(&_Py_path_config); + pathconfig_clear(&_Py_path_config); return; } @@ -437,7 +435,7 @@ Py_SetPath(const wchar_t *path) new_config.program_name = _Py_path_config.program_name; _Py_path_config.program_name = NULL; - _PyPathConfig_Clear(&_Py_path_config); + pathconfig_clear(&_Py_path_config); _Py_path_config = new_config; PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); @@ -569,9 +567,9 @@ Py_GetProgramName(void) Raise an exception and return -1 on error. */ int -_PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p) +_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p) { - assert(_PyWstrList_CheckConsistency(argv)); + assert(_PyWideStringList_CheckConsistency(argv)); if (argv->length == 0) { /* Leave sys.path unchanged if sys.argv is empty */ diff --git a/Python/preconfig.c b/Python/preconfig.c index a6d1346..8be6533 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -1,5 +1,5 @@ #include "Python.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_getopt.h" #include "pycore_pystate.h" /* _PyRuntime_Initialize() */ #include /* setlocale() */ @@ -7,8 +7,13 @@ #define DECODE_LOCALE_ERR(NAME, LEN) \ (((LEN) == -2) \ - ? _Py_INIT_ERR("cannot decode " NAME) \ - : _Py_INIT_NO_MEMORY()) + ? _PyStatus_ERR("cannot decode " NAME) \ + : _PyStatus_NO_MEMORY()) + + +/* Forward declarations */ +static void +preconfig_copy(PyPreConfig *config, const PyPreConfig *config2); /* --- File system encoding/errors -------------------------------- */ @@ -67,22 +72,22 @@ _Py_SetFileSystemEncoding(const char *encoding, const char *errors) /* --- _PyArgv ---------------------------------------------------- */ /* Decode bytes_argv using Py_DecodeLocale() */ -_PyInitError -_PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list) +PyStatus +_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list) { - _PyWstrList wargv = _PyWstrList_INIT; + PyWideStringList wargv = PyWideStringList_INIT; if (args->use_bytes_argv) { size_t size = sizeof(wchar_t*) * args->argc; wargv.items = (wchar_t **)PyMem_RawMalloc(size); if (wargv.items == NULL) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } for (Py_ssize_t i = 0; i < args->argc; i++) { size_t len; wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len); if (arg == NULL) { - _PyWstrList_Clear(&wargv); + _PyWideStringList_Clear(&wargv); return DECODE_LOCALE_ERR("command line arguments", (Py_ssize_t)len); } @@ -90,17 +95,17 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list) wargv.length++; } - _PyWstrList_Clear(list); + _PyWideStringList_Clear(list); *list = wargv; } else { wargv.length = args->argc; wargv.items = (wchar_t **)args->wchar_argv; - if (_PyWstrList_Copy(list, &wargv) < 0) { - return _Py_INIT_NO_MEMORY(); + if (_PyWideStringList_Copy(list, &wargv) < 0) { + return _PyStatus_NO_MEMORY(); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -109,12 +114,12 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list) void _PyPreCmdline_Clear(_PyPreCmdline *cmdline) { - _PyWstrList_Clear(&cmdline->argv); - _PyWstrList_Clear(&cmdline->xoptions); + _PyWideStringList_Clear(&cmdline->argv); + _PyWideStringList_Clear(&cmdline->xoptions); } -_PyInitError +PyStatus _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args) { return _PyArgv_AsWstrList(args, &cmdline->argv); @@ -122,7 +127,7 @@ _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args) static void -_PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config) +precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config) { #define COPY_ATTR(ATTR) \ if (config->ATTR != -1) { \ @@ -138,7 +143,7 @@ _PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config) static void -_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config) +precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config) { #define COPY_ATTR(ATTR) \ config->ATTR = cmdline->ATTR @@ -151,33 +156,34 @@ _PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config) } -int -_PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config) +PyStatus +_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config) { #define COPY_ATTR(ATTR) \ config->ATTR = cmdline->ATTR - if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) { - return -1; + PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions); + if (_PyStatus_EXCEPTION(status)) { + return status; } COPY_ATTR(isolated); COPY_ATTR(use_environment); COPY_ATTR(dev_mode); - return 0; + return _PyStatus_OK(); #undef COPY_ATTR } /* Parse the command line arguments */ -static _PyInitError +static PyStatus precmdline_parse_cmdline(_PyPreCmdline *cmdline) { - const _PyWstrList *argv = &cmdline->argv; + const PyWideStringList *argv = &cmdline->argv; _PyOS_ResetGetOpt(); - /* Don't log parsing errors into stderr here: _PyCoreConfig_Read() + /* Don't log parsing errors into stderr here: PyConfig_Read() is responsible for that */ _PyOS_opterr = 0; do { @@ -199,32 +205,34 @@ precmdline_parse_cmdline(_PyPreCmdline *cmdline) case 'X': { - if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) { - return _Py_INIT_NO_MEMORY(); + PyStatus status = PyWideStringList_Append(&cmdline->xoptions, + _PyOS_optarg); + if (_PyStatus_EXCEPTION(status)) { + return status; } break; } default: /* ignore other argument: - handled by _PyCoreConfig_Read() */ + handled by PyConfig_Read() */ break; } } while (1); - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError -_PyPreCmdline_Read(_PyPreCmdline *cmdline, const _PyPreConfig *preconfig) +PyStatus +_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig) { - _PyPreCmdline_GetPreConfig(cmdline, preconfig); + precmdline_get_preconfig(cmdline, preconfig); if (preconfig->parse_argv) { - _PyInitError err = precmdline_parse_cmdline(cmdline); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = precmdline_parse_cmdline(cmdline); + if (_PyStatus_EXCEPTION(status)) { + return status; } } @@ -254,15 +262,15 @@ _PyPreCmdline_Read(_PyPreCmdline *cmdline, const _PyPreConfig *preconfig) assert(cmdline->isolated >= 0); assert(cmdline->dev_mode >= 0); - return _Py_INIT_OK(); + return _PyStatus_OK(); } -/* --- _PyPreConfig ----------------------------------------------- */ +/* --- PyPreConfig ----------------------------------------------- */ void -_PyPreConfig_InitCompatConfig(_PyPreConfig *config) +_PyPreConfig_InitCompatConfig(PyPreConfig *config) { memset(config, 0, sizeof(*config)); @@ -291,7 +299,7 @@ _PyPreConfig_InitCompatConfig(_PyPreConfig *config) void -_PyPreConfig_InitPythonConfig(_PyPreConfig *config) +PyPreConfig_InitPythonConfig(PyPreConfig *config) { _PyPreConfig_InitCompatConfig(config); @@ -312,7 +320,7 @@ _PyPreConfig_InitPythonConfig(_PyPreConfig *config) void -_PyPreConfig_InitIsolatedConfig(_PyPreConfig *config) +PyPreConfig_InitIsolatedConfig(PyPreConfig *config) { _PyPreConfig_InitCompatConfig(config); @@ -329,37 +337,37 @@ _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config) void -_PyPreConfig_InitFromPreConfig(_PyPreConfig *config, - const _PyPreConfig *config2) +_PyPreConfig_InitFromPreConfig(PyPreConfig *config, + const PyPreConfig *config2) { - _PyPreConfig_InitCompatConfig(config); - _PyPreConfig_Copy(config, config2); + PyPreConfig_InitPythonConfig(config); + preconfig_copy(config, config2); } void -_PyPreConfig_InitFromCoreConfig(_PyPreConfig *config, - const _PyCoreConfig *coreconfig) +_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config) { - _PyConfigInitEnum config_init = (_PyConfigInitEnum)coreconfig->_config_init; + _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init; switch (config_init) { case _PyConfig_INIT_PYTHON: - _PyPreConfig_InitPythonConfig(config); + PyPreConfig_InitPythonConfig(preconfig); break; case _PyConfig_INIT_ISOLATED: - _PyPreConfig_InitIsolatedConfig(config); + PyPreConfig_InitIsolatedConfig(preconfig); break; case _PyConfig_INIT_COMPAT: default: - _PyPreConfig_InitCompatConfig(config); + _PyPreConfig_InitCompatConfig(preconfig); } - _PyPreConfig_GetCoreConfig(config, coreconfig); + _PyPreConfig_GetConfig(preconfig, config); } -void -_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2) +static void +preconfig_copy(PyPreConfig *config, const PyPreConfig *config2) { + assert(config2->_config_version == _Py_CONFIG_VERSION); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR COPY_ATTR(_config_init); @@ -381,7 +389,7 @@ _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2) PyObject* -_PyPreConfig_AsDict(const _PyPreConfig *config) +_PyPreConfig_AsDict(const PyPreConfig *config) { PyObject *dict; @@ -427,12 +435,11 @@ fail: void -_PyPreConfig_GetCoreConfig(_PyPreConfig *config, - const _PyCoreConfig *core_config) +_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config) { #define COPY_ATTR(ATTR) \ - if (core_config->ATTR != -1) { \ - config->ATTR = core_config->ATTR; \ + if (config->ATTR != -1) { \ + preconfig->ATTR = config->ATTR; \ } COPY_ATTR(parse_argv); @@ -445,7 +452,7 @@ _PyPreConfig_GetCoreConfig(_PyPreConfig *config, static void -_PyPreConfig_GetGlobalConfig(_PyPreConfig *config) +preconfig_get_global_vars(PyPreConfig *config) { if (config->_config_init != _PyConfig_INIT_COMPAT) { /* Python and Isolated configuration ignore global variables */ @@ -476,7 +483,7 @@ _PyPreConfig_GetGlobalConfig(_PyPreConfig *config) static void -_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config) +preconfig_set_global_vars(const PyPreConfig *config) { #define COPY_FLAG(ATTR, VAR) \ if (config->ATTR >= 0) { \ @@ -555,7 +562,7 @@ _Py_get_env_flag(int use_environment, int *flag, const char *name) const wchar_t* -_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name) +_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name) { for (Py_ssize_t i=0; i < xoptions->length; i++) { const wchar_t *option = xoptions->items[i]; @@ -575,8 +582,8 @@ _Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name) } -static _PyInitError -preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) +static PyStatus +preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline) { #ifdef MS_WINDOWS if (config->legacy_windows_fs_encoding) { @@ -585,7 +592,7 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) #endif if (config->utf8_mode >= 0) { - return _Py_INIT_OK(); + return _PyStatus_OK(); } const wchar_t *xopt; @@ -601,13 +608,13 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) config->utf8_mode = 0; } else { - return _Py_INIT_ERR("invalid -X utf8 option value"); + return _PyStatus_ERR("invalid -X utf8 option value"); } } else { config->utf8_mode = 1; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8"); @@ -619,10 +626,10 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) config->utf8_mode = 0; } else { - return _Py_INIT_ERR("invalid PYTHONUTF8 environment " + return _PyStatus_ERR("invalid PYTHONUTF8 environment " "variable value"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -642,12 +649,12 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) if (config->utf8_mode < 0) { config->utf8_mode = 0; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } static void -preconfig_init_coerce_c_locale(_PyPreConfig *config) +preconfig_init_coerce_c_locale(PyPreConfig *config) { if (!config->configure_locale) { config->coerce_c_locale = 0; @@ -693,8 +700,8 @@ preconfig_init_coerce_c_locale(_PyPreConfig *config) } -static _PyInitError -preconfig_init_allocator(_PyPreConfig *config) +static PyStatus +preconfig_init_allocator(PyPreConfig *config) { if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) { /* bpo-34247. The PYTHONMALLOC environment variable has the priority @@ -705,7 +712,7 @@ preconfig_init_allocator(_PyPreConfig *config) if (envvar) { PyMemAllocatorName name; if (_PyMem_GetAllocatorName(envvar, &name) < 0) { - return _Py_INIT_ERR("PYTHONMALLOC: unknown allocator"); + return _PyStatus_ERR("PYTHONMALLOC: unknown allocator"); } config->allocator = (int)name; } @@ -714,21 +721,21 @@ preconfig_init_allocator(_PyPreConfig *config) if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) { config->allocator = PYMEM_ALLOCATOR_DEBUG; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError -preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline) +static PyStatus +preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline) { - _PyInitError err; + PyStatus status; - err = _PyPreCmdline_Read(cmdline, config); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyPreCmdline_Read(cmdline, config); + if (_PyStatus_EXCEPTION(status)) { + return status; } - _PyPreCmdline_SetPreConfig(cmdline, config); + precmdline_set_preconfig(cmdline, config); /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */ #ifdef MS_WINDOWS @@ -739,15 +746,15 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline) preconfig_init_coerce_c_locale(config); - err = preconfig_init_utf8_mode(config, cmdline); - if (_Py_INIT_FAILED(err)) { - return err; + status = preconfig_init_utf8_mode(config, cmdline); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* allocator */ - err = preconfig_init_allocator(config); - if (_Py_INIT_FAILED(err)) { - return err; + status = preconfig_init_allocator(config); + if (_PyStatus_EXCEPTION(status)) { + return status; } assert(config->coerce_c_locale >= 0); @@ -760,7 +767,7 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline) assert(config->use_environment >= 0); assert(config->dev_mode >= 0); - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -770,30 +777,30 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline) - environment variables - Py_xxx global configuration variables - the LC_CTYPE locale */ -_PyInitError -_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) +PyStatus +_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args) { - _PyInitError err; + PyStatus status; - err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } - _PyPreConfig_GetGlobalConfig(config); + preconfig_get_global_vars(config); /* Copy LC_CTYPE locale, since it's modified later */ const char *loc = setlocale(LC_CTYPE, NULL); if (loc == NULL) { - return _Py_INIT_ERR("failed to LC_CTYPE locale"); + return _PyStatus_ERR("failed to LC_CTYPE locale"); } char *init_ctype_locale = _PyMem_RawStrdup(loc); if (init_ctype_locale == NULL) { - return _Py_INIT_NO_MEMORY(); + return _PyStatus_NO_MEMORY(); } /* Save the config to be able to restore it if encodings change */ - _PyPreConfig save_config; + PyPreConfig save_config; _PyPreConfig_InitFromPreConfig(&save_config, config); /* Set LC_CTYPE to the user preferred locale */ @@ -808,8 +815,8 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) #endif if (args) { - err = _PyPreCmdline_SetArgv(&cmdline, args); - if (_Py_INIT_FAILED(err)) { + status = _PyPreCmdline_SetArgv(&cmdline, args); + if (_PyStatus_EXCEPTION(status)) { goto done; } } @@ -823,7 +830,7 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) /* Watchdog to prevent an infinite loop */ loops++; if (loops == 3) { - err = _Py_INIT_ERR("Encoding changed twice while " + status = _PyStatus_ERR("Encoding changed twice while " "reading the configuration"); goto done; } @@ -835,8 +842,8 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding; #endif - err = preconfig_read(config, &cmdline); - if (_Py_INIT_FAILED(err)) { + status = preconfig_read(config, &cmdline); + if (_PyStatus_EXCEPTION(status)) { goto done; } @@ -877,14 +884,14 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) just keep UTF-8 Mode value. */ int new_utf8_mode = config->utf8_mode; int new_coerce_c_locale = config->coerce_c_locale; - _PyPreConfig_Copy(config, &save_config); + preconfig_copy(config, &save_config); config->utf8_mode = new_utf8_mode; config->coerce_c_locale = new_coerce_c_locale; /* The encoding changed: read again the configuration with the new encoding */ } - err = _Py_INIT_OK(); + status = _PyStatus_OK(); done: if (init_ctype_locale != NULL) { @@ -896,7 +903,7 @@ done: Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding; #endif _PyPreCmdline_Clear(&cmdline); - return err; + return status; } @@ -912,26 +919,26 @@ done: Do nothing if called after Py_Initialize(): ignore the new pre-configuration. */ -_PyInitError -_PyPreConfig_Write(const _PyPreConfig *src_config) +PyStatus +_PyPreConfig_Write(const PyPreConfig *src_config) { - _PyPreConfig config; + PyPreConfig config; _PyPreConfig_InitFromPreConfig(&config, src_config); if (_PyRuntime.core_initialized) { /* bpo-34008: Calling this functions after Py_Initialize() ignores the new configuration. */ - return _Py_INIT_OK(); + return _PyStatus_OK(); } PyMemAllocatorName name = (PyMemAllocatorName)config.allocator; if (name != PYMEM_ALLOCATOR_NOT_SET) { if (_PyMem_SetupAllocators(name) < 0) { - return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator"); + return _PyStatus_ERR("Unknown PYTHONMALLOC allocator"); } } - _PyPreConfig_SetGlobalConfig(&config); + preconfig_set_global_vars(&config); if (config.configure_locale) { if (config.coerce_c_locale) { @@ -946,7 +953,7 @@ _PyPreConfig_Write(const _PyPreConfig *src_config) } /* Write the new pre-configuration into _PyRuntime */ - _PyPreConfig_Copy(&_PyRuntime.preconfig, &config); + preconfig_copy(&_PyRuntime.preconfig, &config); - return _Py_INIT_OK(); + return _PyStatus_OK(); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 9880c0d..10a2881 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -6,7 +6,7 @@ #undef Yield /* undefine macro conflicting with */ #include "pycore_ceval.h" #include "pycore_context.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_fileutils.h" #include "pycore_hamt.h" #include "pycore_pathconfig.h" @@ -60,10 +60,10 @@ extern "C" { extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ -static _PyInitError add_main_module(PyInterpreterState *interp); -static _PyInitError init_import_size(void); -static _PyInitError init_sys_streams(PyInterpreterState *interp); -static _PyInitError init_signals(void); +static PyStatus add_main_module(PyInterpreterState *interp); +static PyStatus init_import_size(void); +static PyStatus init_sys_streams(PyInterpreterState *interp); +static PyStatus init_signals(void); static void call_py_exitfuncs(PyInterpreterState *); static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(_PyRuntimeState *runtime); @@ -72,7 +72,7 @@ int _Py_UnhandledKeyboardInterrupt = 0; _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; static int runtime_initialized = 0; -_PyInitError +PyStatus _PyRuntime_Initialize(void) { /* XXX We only initialize once in the process, which aligns with @@ -82,7 +82,7 @@ _PyRuntime_Initialize(void) This is because the runtime state is not properly finalized currently. */ if (runtime_initialized) { - return _Py_INIT_OK(); + return _PyStatus_OK(); } runtime_initialized = 1; @@ -145,58 +145,58 @@ Py_IsInitialized(void) */ -static _PyInitError +static PyStatus init_importlib(PyInterpreterState *interp, PyObject *sysmod) { PyObject *importlib; PyObject *impmod; PyObject *value; - int verbose = interp->core_config.verbose; + int verbose = interp->config.verbose; /* Import _importlib through its frozen version, _frozen_importlib. */ if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) { - return _Py_INIT_ERR("can't import _frozen_importlib"); + return _PyStatus_ERR("can't import _frozen_importlib"); } else if (verbose) { PySys_FormatStderr("import _frozen_importlib # frozen\n"); } importlib = PyImport_AddModule("_frozen_importlib"); if (importlib == NULL) { - return _Py_INIT_ERR("couldn't get _frozen_importlib from sys.modules"); + return _PyStatus_ERR("couldn't get _frozen_importlib from sys.modules"); } interp->importlib = importlib; Py_INCREF(interp->importlib); interp->import_func = PyDict_GetItemString(interp->builtins, "__import__"); if (interp->import_func == NULL) - return _Py_INIT_ERR("__import__ not found"); + return _PyStatus_ERR("__import__ not found"); Py_INCREF(interp->import_func); /* Import the _imp module */ impmod = PyInit__imp(); if (impmod == NULL) { - return _Py_INIT_ERR("can't import _imp"); + return _PyStatus_ERR("can't import _imp"); } else if (verbose) { PySys_FormatStderr("import _imp # builtin\n"); } if (_PyImport_SetModuleString("_imp", impmod) < 0) { - return _Py_INIT_ERR("can't save _imp to sys.modules"); + return _PyStatus_ERR("can't save _imp to sys.modules"); } /* Install importlib as the implementation of import */ value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod); if (value == NULL) { PyErr_Print(); - return _Py_INIT_ERR("importlib install failed"); + return _PyStatus_ERR("importlib install failed"); } Py_DECREF(value); Py_DECREF(impmod); - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus init_importlib_external(PyInterpreterState *interp) { PyObject *value; @@ -204,7 +204,7 @@ init_importlib_external(PyInterpreterState *interp) "_install_external_importers", ""); if (value == NULL) { PyErr_Print(); - return _Py_INIT_ERR("external importer setup failed"); + return _PyStatus_ERR("external importer setup failed"); } Py_DECREF(value); return _PyImportZip_Init(interp); @@ -265,7 +265,7 @@ static const char *_C_LOCALE_WARNING = static void emit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime) { - const _PyPreConfig *preconfig = &runtime->preconfig; + const PyPreConfig *preconfig = &runtime->preconfig; if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected(1)) { PySys_FormatStderr("%s", _C_LOCALE_WARNING); } @@ -437,7 +437,7 @@ _Py_SetLocaleFromEnv(int category) /* Global initializations. Can be undone by Py_Finalize(). Don't call this twice without an intervening Py_Finalize() call. - Every call to _Py_InitializeFromConfig, Py_Initialize or Py_InitializeEx + Every call to Py_InitializeFromConfig, Py_Initialize or Py_InitializeEx must have a corresponding call to Py_Finalize. Locking: you must hold the interpreter lock while calling these APIs. @@ -446,50 +446,50 @@ _Py_SetLocaleFromEnv(int category) */ -static _PyInitError +static PyStatus pyinit_core_reconfigure(_PyRuntimeState *runtime, PyInterpreterState **interp_p, - const _PyCoreConfig *core_config) + const PyConfig *config) { - _PyInitError err; + PyStatus status; PyThreadState *tstate = _PyThreadState_GET(); if (!tstate) { - return _Py_INIT_ERR("failed to read thread state"); + return _PyStatus_ERR("failed to read thread state"); } PyInterpreterState *interp = tstate->interp; if (interp == NULL) { - return _Py_INIT_ERR("can't make main interpreter"); + return _PyStatus_ERR("can't make main interpreter"); } *interp_p = interp; - _PyCoreConfig_Write(core_config, runtime); + _PyConfig_Write(config, runtime); - err = _PyCoreConfig_Copy(&interp->core_config, core_config); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyConfig_Copy(&interp->config, config); + if (_PyStatus_EXCEPTION(status)) { + return status; } - core_config = &interp->core_config; + config = &interp->config; - if (core_config->_install_importlib) { - err = _PyCoreConfig_SetPathConfig(core_config); - if (_Py_INIT_FAILED(err)) { - return err; + if (config->_install_importlib) { + status = _PyConfig_SetPathConfig(config); + if (_PyStatus_EXCEPTION(status)) { + return status; } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus pycore_init_runtime(_PyRuntimeState *runtime, - const _PyCoreConfig *core_config) + const PyConfig *config) { if (runtime->initialized) { - return _Py_INIT_ERR("main interpreter already initialized"); + return _PyStatus_ERR("main interpreter already initialized"); } - _PyCoreConfig_Write(core_config, runtime); + _PyConfig_Write(config, runtime); /* Py_Finalize leaves _Py_Finalizing set in order to help daemon * threads behave a little more gracefully at interpreter shutdown. @@ -502,39 +502,39 @@ pycore_init_runtime(_PyRuntimeState *runtime, */ runtime->finalizing = NULL; - _PyInitError err = _Py_HashRandomization_Init(core_config); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _Py_HashRandomization_Init(config); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyInterpreterState_Enable(runtime); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyInterpreterState_Enable(runtime); + if (_PyStatus_EXCEPTION(status)) { + return status; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus pycore_create_interpreter(_PyRuntimeState *runtime, - const _PyCoreConfig *core_config, + const PyConfig *config, PyInterpreterState **interp_p) { PyInterpreterState *interp = PyInterpreterState_New(); if (interp == NULL) { - return _Py_INIT_ERR("can't make main interpreter"); + return _PyStatus_ERR("can't make main interpreter"); } *interp_p = interp; - _PyInitError err = _PyCoreConfig_Copy(&interp->core_config, core_config); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PyConfig_Copy(&interp->config, config); + if (_PyStatus_EXCEPTION(status)) { + return status; } - core_config = &interp->core_config; + config = &interp->config; PyThreadState *tstate = PyThreadState_New(interp); if (tstate == NULL) - return _Py_INIT_ERR("can't make first thread"); + return _PyStatus_ERR("can't make first thread"); (void) PyThreadState_Swap(tstate); /* We can't call _PyEval_FiniThreads() in Py_FinalizeEx because @@ -550,249 +550,249 @@ pycore_create_interpreter(_PyRuntimeState *runtime, /* Create the GIL */ PyEval_InitThreads(); - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus pycore_init_types(void) { - _PyInitError err = _PyTypes_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PyTypes_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyUnicode_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyUnicode_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (_PyStructSequence_Init() < 0) { - return _Py_INIT_ERR("can't initialize structseq"); + return _PyStatus_ERR("can't initialize structseq"); } if (!_PyLong_Init()) { - return _Py_INIT_ERR("can't init longs"); + return _PyStatus_ERR("can't init longs"); } - err = _PyExc_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyExc_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (!_PyFloat_Init()) { - return _Py_INIT_ERR("can't init float"); + return _PyStatus_ERR("can't init float"); } if (!_PyContext_Init()) { - return _Py_INIT_ERR("can't init context"); + return _PyStatus_ERR("can't init context"); } - err = _PyErr_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyErr_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus pycore_init_builtins(PyInterpreterState *interp) { PyObject *bimod = _PyBuiltin_Init(); if (bimod == NULL) { - return _Py_INIT_ERR("can't initialize builtins modules"); + return _PyStatus_ERR("can't initialize builtins modules"); } _PyImport_FixupBuiltin(bimod, "builtins", interp->modules); interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) { - return _Py_INIT_ERR("can't initialize builtins dict"); + return _PyStatus_ERR("can't initialize builtins dict"); } Py_INCREF(interp->builtins); - _PyInitError err = _PyBuiltins_AddExceptions(bimod); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PyBuiltins_AddExceptions(bimod); + if (_PyStatus_EXCEPTION(status)) { + return status; } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError +static PyStatus pycore_init_import_warnings(PyInterpreterState *interp, PyObject *sysmod) { - _PyInitError err = _PyImport_Init(interp); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PyImport_Init(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyImportHooks_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyImportHooks_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* Initialize _warnings. */ if (_PyWarnings_Init() == NULL) { - return _Py_INIT_ERR("can't initialize warnings"); + return _PyStatus_ERR("can't initialize warnings"); } - if (interp->core_config._install_importlib) { - err = _PyCoreConfig_SetPathConfig(&interp->core_config); - if (_Py_INIT_FAILED(err)) { - return err; + if (interp->config._install_importlib) { + status = _PyConfig_SetPathConfig(&interp->config); + if (_PyStatus_EXCEPTION(status)) { + return status; } } /* This call sets up builtin and frozen import support */ - if (interp->core_config._install_importlib) { - err = init_importlib(interp, sysmod); - if (_Py_INIT_FAILED(err)) { - return err; + if (interp->config._install_importlib) { + status = init_importlib(interp, sysmod); + if (_PyStatus_EXCEPTION(status)) { + return status; } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } -static _PyInitError -pyinit_core_config(_PyRuntimeState *runtime, - PyInterpreterState **interp_p, - const _PyCoreConfig *core_config) +static PyStatus +pyinit_config(_PyRuntimeState *runtime, + PyInterpreterState **interp_p, + const PyConfig *config) { PyInterpreterState *interp; - _PyCoreConfig_Write(core_config, runtime); + _PyConfig_Write(config, runtime); - _PyInitError err = pycore_init_runtime(runtime, core_config); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = pycore_init_runtime(runtime, config); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = pycore_create_interpreter(runtime, core_config, &interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = pycore_create_interpreter(runtime, config, &interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - core_config = &interp->core_config; + config = &interp->config; *interp_p = interp; - err = pycore_init_types(); - if (_Py_INIT_FAILED(err)) { - return err; + status = pycore_init_types(); + if (_PyStatus_EXCEPTION(status)) { + return status; } PyObject *sysmod; - err = _PySys_Create(runtime, interp, &sysmod); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PySys_Create(runtime, interp, &sysmod); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = pycore_init_builtins(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = pycore_init_builtins(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = pycore_init_import_warnings(interp, sysmod); - if (_Py_INIT_FAILED(err)) { - return err; + status = pycore_init_import_warnings(interp, sysmod); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* Only when we get here is the runtime core fully initialized */ runtime->core_initialized = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError -_Py_PreInitializeFromPyArgv(const _PyPreConfig *src_config, const _PyArgv *args) +PyStatus +_Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args) { - _PyInitError err; + PyStatus status; if (src_config == NULL) { - return _Py_INIT_ERR("preinitialization config is NULL"); + return _PyStatus_ERR("preinitialization config is NULL"); } - err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } _PyRuntimeState *runtime = &_PyRuntime; if (runtime->pre_initialized) { /* If it's already configured: ignored the new configuration */ - return _Py_INIT_OK(); + return _PyStatus_OK(); } - _PyPreConfig config; + PyPreConfig config; _PyPreConfig_InitFromPreConfig(&config, src_config); - err = _PyPreConfig_Read(&config, args); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyPreConfig_Read(&config, args); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyPreConfig_Write(&config); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyPreConfig_Write(&config); + if (_PyStatus_EXCEPTION(status)) { + return status; } runtime->pre_initialized = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError -_Py_PreInitializeFromArgs(const _PyPreConfig *src_config, Py_ssize_t argc, char **argv) +PyStatus +Py_PreInitializeFromBytesArgs(const PyPreConfig *src_config, Py_ssize_t argc, char **argv) { _PyArgv args = {.use_bytes_argv = 1, .argc = argc, .bytes_argv = argv}; return _Py_PreInitializeFromPyArgv(src_config, &args); } -_PyInitError -_Py_PreInitializeFromWideArgs(const _PyPreConfig *src_config, Py_ssize_t argc, wchar_t **argv) +PyStatus +Py_PreInitializeFromArgs(const PyPreConfig *src_config, Py_ssize_t argc, wchar_t **argv) { _PyArgv args = {.use_bytes_argv = 0, .argc = argc, .wchar_argv = argv}; return _Py_PreInitializeFromPyArgv(src_config, &args); } -_PyInitError -_Py_PreInitialize(const _PyPreConfig *src_config) +PyStatus +Py_PreInitialize(const PyPreConfig *src_config) { return _Py_PreInitializeFromPyArgv(src_config, NULL); } -_PyInitError -_Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig, - const _PyArgv *args) +PyStatus +_Py_PreInitializeFromConfig(const PyConfig *config, + const _PyArgv *args) { - assert(coreconfig != NULL); + assert(config != NULL); - _PyInitError err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } _PyRuntimeState *runtime = &_PyRuntime; if (runtime->pre_initialized) { /* Already initialized: do nothing */ - return _Py_INIT_OK(); + return _PyStatus_OK(); } - _PyPreConfig preconfig; - _PyPreConfig_InitFromCoreConfig(&preconfig, coreconfig); + PyPreConfig preconfig; + _PyPreConfig_InitFromConfig(&preconfig, config); - if (!coreconfig->parse_argv) { - return _Py_PreInitialize(&preconfig); + if (!config->parse_argv) { + return Py_PreInitialize(&preconfig); } else if (args == NULL) { _PyArgv config_args = { .use_bytes_argv = 0, - .argc = coreconfig->argv.length, - .wchar_argv = coreconfig->argv.items}; + .argc = config->argv.length, + .wchar_argv = config->argv.items}; return _Py_PreInitializeFromPyArgv(&preconfig, &config_args); } else { @@ -818,74 +818,66 @@ _Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig, * to the Python C API (unless the API is explicitly listed as being * safe to call without calling Py_Initialize first) */ -static _PyInitError +static PyStatus pyinit_core(_PyRuntimeState *runtime, - const _PyCoreConfig *src_config, - const _PyArgv *args, + const PyConfig *src_config, PyInterpreterState **interp_p) { - _PyInitError err; + PyStatus status; - err = _Py_PreInitializeFromCoreConfig(src_config, args); - if (_Py_INIT_FAILED(err)) { - return err; + status = _Py_PreInitializeFromConfig(src_config, NULL); + if (_PyStatus_EXCEPTION(status)) { + return status; } - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + PyConfig config; + _PyConfig_InitCompatConfig(&config); - err = _PyCoreConfig_Copy(&config, src_config); - if (_Py_INIT_FAILED(err)) { + status = _PyConfig_Copy(&config, src_config); + if (_PyStatus_EXCEPTION(status)) { goto done; } - if (args) { - err = _PyCoreConfig_SetPyArgv(&config, args); - if (_Py_INIT_FAILED(err)) { - goto done; - } - } - - err = _PyCoreConfig_Read(&config); - if (_Py_INIT_FAILED(err)) { + status = PyConfig_Read(&config); + if (_PyStatus_EXCEPTION(status)) { goto done; } if (!runtime->core_initialized) { - err = pyinit_core_config(runtime, interp_p, &config); + status = pyinit_config(runtime, interp_p, &config); } else { - err = pyinit_core_reconfigure(runtime, interp_p, &config); + status = pyinit_core_reconfigure(runtime, interp_p, &config); } - if (_Py_INIT_FAILED(err)) { + if (_PyStatus_EXCEPTION(status)) { goto done; } done: - _PyCoreConfig_Clear(&config); - return err; + PyConfig_Clear(&config); + return status; } /* Py_Initialize() has already been called: update the main interpreter configuration. Example of bpo-34008: Py_Main() called after Py_Initialize(). */ -static _PyInitError +static PyStatus _Py_ReconfigureMainInterpreter(PyInterpreterState *interp) { - _PyCoreConfig *core_config = &interp->core_config; + PyConfig *config = &interp->config; - PyObject *argv = _PyWstrList_AsList(&core_config->argv); + PyObject *argv = _PyWideStringList_AsList(&config->argv); if (argv == NULL) { - return _Py_INIT_NO_MEMORY(); \ + return _PyStatus_NO_MEMORY(); \ } int res = PyDict_SetItemString(interp->sysdict, "argv", argv); Py_DECREF(argv); if (res < 0) { - return _Py_INIT_ERR("fail to set sys.argv"); + return _PyStatus_ERR("fail to set sys.argv"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Update interpreter state based on supplied configuration settings @@ -899,73 +891,73 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp) * Other errors should be reported as normal Python exceptions with a * non-zero return code. */ -static _PyInitError +static PyStatus pyinit_main(_PyRuntimeState *runtime, PyInterpreterState *interp) { if (!runtime->core_initialized) { - return _Py_INIT_ERR("runtime core not initialized"); + return _PyStatus_ERR("runtime core not initialized"); } /* Configure the main interpreter */ - _PyCoreConfig *core_config = &interp->core_config; + PyConfig *config = &interp->config; if (runtime->initialized) { return _Py_ReconfigureMainInterpreter(interp); } - if (!core_config->_install_importlib) { + if (!config->_install_importlib) { /* Special mode for freeze_importlib: run with no import system * * This means anything which needs support from extension modules * or pure Python code in the standard library won't work. */ runtime->initialized = 1; - return _Py_INIT_OK(); + return _PyStatus_OK(); } if (_PyTime_Init() < 0) { - return _Py_INIT_ERR("can't initialize time"); + return _PyStatus_ERR("can't initialize time"); } if (_PySys_InitMain(runtime, interp) < 0) { - return _Py_INIT_ERR("can't finish initializing sys"); + return _PyStatus_ERR("can't finish initializing sys"); } - _PyInitError err = init_importlib_external(interp); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = init_importlib_external(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* initialize the faulthandler module */ - err = _PyFaulthandler_Init(core_config->faulthandler); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyFaulthandler_Init(config->faulthandler); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyUnicode_InitEncodings(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyUnicode_InitEncodings(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - if (core_config->install_signal_handlers) { - err = init_signals(); - if (_Py_INIT_FAILED(err)) { - return err; + if (config->install_signal_handlers) { + status = init_signals(); + if (_PyStatus_EXCEPTION(status)) { + return status; } } - if (_PyTraceMalloc_Init(core_config->tracemalloc) < 0) { - return _Py_INIT_ERR("can't initialize tracemalloc"); + if (_PyTraceMalloc_Init(config->tracemalloc) < 0) { + return _PyStatus_ERR("can't initialize tracemalloc"); } - err = add_main_module(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = add_main_module(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = init_sys_streams(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = init_sys_streams(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* Initialize warnings. */ @@ -982,10 +974,10 @@ pyinit_main(_PyRuntimeState *runtime, PyInterpreterState *interp) runtime->initialized = 1; - if (core_config->site_import) { - err = init_import_size(); /* Module site */ - if (_Py_INIT_FAILED(err)) { - return err; + if (config->site_import) { + status = init_import_size(); /* Module site */ + if (_PyStatus_EXCEPTION(status)) { + return status; } } @@ -993,16 +985,16 @@ pyinit_main(_PyRuntimeState *runtime, PyInterpreterState *interp) emit_stderr_warning_for_legacy_locale(runtime); #endif - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError +PyStatus _Py_InitializeMain(void) { - _PyInitError err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } _PyRuntimeState *runtime = &_PyRuntime; PyInterpreterState *interp = _PyRuntimeState_GetThreadState(runtime)->interp; @@ -1011,74 +1003,47 @@ _Py_InitializeMain(void) } -#undef _INIT_DEBUG_PRINT - -static _PyInitError -pyinit_python(const _PyCoreConfig *config, const _PyArgv *args) +PyStatus +Py_InitializeFromConfig(const PyConfig *config) { if (config == NULL) { - return _Py_INIT_ERR("initialization config is NULL"); + return _PyStatus_ERR("initialization config is NULL"); } - _PyInitError err; + PyStatus status; - err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } _PyRuntimeState *runtime = &_PyRuntime; PyInterpreterState *interp = NULL; - err = pyinit_core(runtime, config, args, &interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = pyinit_core(runtime, config, &interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - config = &interp->core_config; + config = &interp->config; if (config->_init_main) { - err = pyinit_main(runtime, interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = pyinit_main(runtime, interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } } - return _Py_INIT_OK(); -} - - -_PyInitError -_Py_InitializeFromArgs(const _PyCoreConfig *config, - Py_ssize_t argc, char * const *argv) -{ - _PyArgv args = {.use_bytes_argv = 1, .argc = argc, .bytes_argv = argv}; - return pyinit_python(config, &args); -} - - -_PyInitError -_Py_InitializeFromWideArgs(const _PyCoreConfig *config, - Py_ssize_t argc, wchar_t * const *argv) -{ - _PyArgv args = {.use_bytes_argv = 0, .argc = argc, .wchar_argv = argv}; - return pyinit_python(config, &args); -} - - -_PyInitError -_Py_InitializeFromConfig(const _PyCoreConfig *config) -{ - return pyinit_python(config, NULL); + return _PyStatus_OK(); } void Py_InitializeEx(int install_sigs) { - _PyInitError err; + PyStatus status; - err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - _Py_ExitInitError(err); + status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + Py_ExitStatusException(status); } _PyRuntimeState *runtime = &_PyRuntime; @@ -1087,13 +1052,13 @@ Py_InitializeEx(int install_sigs) return; } - _PyCoreConfig config; - _PyCoreConfig_InitCompatConfig(&config); + PyConfig config; + _PyConfig_InitCompatConfig(&config); config.install_signal_handlers = install_sigs; - err = _Py_InitializeFromConfig(&config); - if (_Py_INIT_FAILED(err)) { - _Py_ExitInitError(err); + status = Py_InitializeFromConfig(&config); + if (_PyStatus_EXCEPTION(status)) { + Py_ExitStatusException(status); } } @@ -1206,13 +1171,13 @@ Py_FinalizeEx(void) /* Copy the core config, PyInterpreterState_Delete() free the core config memory */ #ifdef Py_REF_DEBUG - int show_ref_count = interp->core_config.show_ref_count; + int show_ref_count = interp->config.show_ref_count; #endif #ifdef Py_TRACE_REFS - int dump_refs = interp->core_config.dump_refs; + int dump_refs = interp->config.dump_refs; #endif #ifdef WITH_PYMALLOC - int malloc_stats = interp->core_config.malloc_stats; + int malloc_stats = interp->config.malloc_stats; #endif /* Remaining threads (e.g. daemon threads) will automatically exit @@ -1412,19 +1377,19 @@ Py_Finalize(void) */ -static _PyInitError +static PyStatus new_interpreter(PyThreadState **tstate_p) { - _PyInitError err; + PyStatus status; - err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; } _PyRuntimeState *runtime = &_PyRuntime; if (!runtime->initialized) { - return _Py_INIT_ERR("Py_Initialize must be called first"); + return _PyStatus_ERR("Py_Initialize must be called first"); } /* Issue #10915, #15751: The GIL API doesn't work with multiple @@ -1434,49 +1399,49 @@ new_interpreter(PyThreadState **tstate_p) PyInterpreterState *interp = PyInterpreterState_New(); if (interp == NULL) { *tstate_p = NULL; - return _Py_INIT_OK(); + return _PyStatus_OK(); } PyThreadState *tstate = PyThreadState_New(interp); if (tstate == NULL) { PyInterpreterState_Delete(interp); *tstate_p = NULL; - return _Py_INIT_OK(); + return _PyStatus_OK(); } PyThreadState *save_tstate = PyThreadState_Swap(tstate); /* Copy the current interpreter config into the new interpreter */ - _PyCoreConfig *core_config; + PyConfig *config; if (save_tstate != NULL) { - core_config = &save_tstate->interp->core_config; + config = &save_tstate->interp->config; } else { /* No current thread state, copy from the main interpreter */ PyInterpreterState *main_interp = PyInterpreterState_Main(); - core_config = &main_interp->core_config; + config = &main_interp->config; } - err = _PyCoreConfig_Copy(&interp->core_config, core_config); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyConfig_Copy(&interp->config, config); + if (_PyStatus_EXCEPTION(status)) { + return status; } - core_config = &interp->core_config; + config = &interp->config; - err = _PyExc_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyExc_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyErr_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyErr_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } /* XXX The following is lax in error checking */ PyObject *modules = PyDict_New(); if (modules == NULL) { - return _Py_INIT_ERR("can't make modules dictionary"); + return _PyStatus_ERR("can't make modules dictionary"); } interp->modules = modules; @@ -1489,7 +1454,7 @@ new_interpreter(PyThreadState **tstate_p) Py_INCREF(interp->sysdict); PyDict_SetItemString(interp->sysdict, "modules", modules); if (_PySys_InitMain(runtime, interp) < 0) { - return _Py_INIT_ERR("can't finish initializing sys"); + return _PyStatus_ERR("can't finish initializing sys"); } } else if (PyErr_Occurred()) { @@ -1508,50 +1473,50 @@ new_interpreter(PyThreadState **tstate_p) } if (bimod != NULL && sysmod != NULL) { - err = _PyBuiltins_AddExceptions(bimod); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyBuiltins_AddExceptions(bimod); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PySys_SetPreliminaryStderr(interp->sysdict); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PySys_SetPreliminaryStderr(interp->sysdict); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyImportHooks_Init(); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyImportHooks_Init(); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = init_importlib(interp, sysmod); - if (_Py_INIT_FAILED(err)) { - return err; + status = init_importlib(interp, sysmod); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = init_importlib_external(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = init_importlib_external(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PyUnicode_InitEncodings(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PyUnicode_InitEncodings(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = init_sys_streams(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = init_sys_streams(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = add_main_module(interp); - if (_Py_INIT_FAILED(err)) { - return err; + status = add_main_module(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - if (core_config->site_import) { - err = init_import_size(); - if (_Py_INIT_FAILED(err)) { - return err; + if (config->site_import) { + status = init_import_size(); + if (_PyStatus_EXCEPTION(status)) { + return status; } } } @@ -1561,7 +1526,7 @@ new_interpreter(PyThreadState **tstate_p) } *tstate_p = tstate; - return _Py_INIT_OK(); + return _PyStatus_OK(); handle_error: /* Oops, it didn't work. Undo it all. */ @@ -1573,16 +1538,16 @@ handle_error: PyInterpreterState_Delete(interp); *tstate_p = NULL; - return _Py_INIT_OK(); + return _PyStatus_OK(); } PyThreadState * Py_NewInterpreter(void) { PyThreadState *tstate = NULL; - _PyInitError err = new_interpreter(&tstate); - if (_Py_INIT_FAILED(err)) { - _Py_ExitInitError(err); + PyStatus status = new_interpreter(&tstate); + if (_PyStatus_EXCEPTION(status)) { + Py_ExitStatusException(status); } return tstate; @@ -1627,29 +1592,29 @@ Py_EndInterpreter(PyThreadState *tstate) /* Add the __main__ module */ -static _PyInitError +static PyStatus add_main_module(PyInterpreterState *interp) { PyObject *m, *d, *loader, *ann_dict; m = PyImport_AddModule("__main__"); if (m == NULL) - return _Py_INIT_ERR("can't create __main__ module"); + return _PyStatus_ERR("can't create __main__ module"); d = PyModule_GetDict(m); ann_dict = PyDict_New(); if ((ann_dict == NULL) || (PyDict_SetItemString(d, "__annotations__", ann_dict) < 0)) { - return _Py_INIT_ERR("Failed to initialize __main__.__annotations__"); + return _PyStatus_ERR("Failed to initialize __main__.__annotations__"); } Py_DECREF(ann_dict); if (PyDict_GetItemString(d, "__builtins__") == NULL) { PyObject *bimod = PyImport_ImportModule("builtins"); if (bimod == NULL) { - return _Py_INIT_ERR("Failed to retrieve builtins module"); + return _PyStatus_ERR("Failed to retrieve builtins module"); } if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) { - return _Py_INIT_ERR("Failed to initialize __main__.__builtins__"); + return _PyStatus_ERR("Failed to initialize __main__.__builtins__"); } Py_DECREF(bimod); } @@ -1665,28 +1630,28 @@ add_main_module(PyInterpreterState *interp) PyObject *loader = PyObject_GetAttrString(interp->importlib, "BuiltinImporter"); if (loader == NULL) { - return _Py_INIT_ERR("Failed to retrieve BuiltinImporter"); + return _PyStatus_ERR("Failed to retrieve BuiltinImporter"); } if (PyDict_SetItemString(d, "__loader__", loader) < 0) { - return _Py_INIT_ERR("Failed to initialize __main__.__loader__"); + return _PyStatus_ERR("Failed to initialize __main__.__loader__"); } Py_DECREF(loader); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Import the site module (not into __main__ though) */ -static _PyInitError +static PyStatus init_import_size(void) { PyObject *m; m = PyImport_ImportModule("site"); if (m == NULL) { - return _Py_INIT_ERR("Failed to import the site module"); + return _PyStatus_ERR("Failed to import the site module"); } Py_DECREF(m); - return _Py_INIT_OK(); + return _PyStatus_OK(); } /* Check if a file descriptor is valid or not. @@ -1727,7 +1692,7 @@ is_valid_fd(int fd) /* returns Py_None if the fd is not valid */ static PyObject* -create_stdio(const _PyCoreConfig *config, PyObject* io, +create_stdio(const PyConfig *config, PyObject* io, int fd, int write_mode, const char* name, const wchar_t* encoding, const wchar_t* errors) { @@ -1864,7 +1829,7 @@ error: } /* Initialize sys.stdin, stdout, stderr and builtins.open */ -static _PyInitError +static PyStatus init_sys_streams(PyInterpreterState *interp) { PyObject *iomod = NULL, *wrapper; @@ -1873,8 +1838,8 @@ init_sys_streams(PyInterpreterState *interp) PyObject *std = NULL; int fd; PyObject * encoding_attr; - _PyInitError res = _Py_INIT_OK(); - _PyCoreConfig *config = &interp->core_config; + PyStatus res = _PyStatus_OK(); + PyConfig *config = &interp->config; /* Check that stdin is not a directory Using shell redirection, you can redirect stdin to a directory, @@ -1885,7 +1850,7 @@ init_sys_streams(PyInterpreterState *interp) struct _Py_stat_struct sb; if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 && S_ISDIR(sb.st_mode)) { - return _Py_INIT_ERR(" is a directory, cannot continue"); + return _PyStatus_ERR(" is a directory, cannot continue"); } #endif @@ -1981,7 +1946,7 @@ init_sys_streams(PyInterpreterState *interp) goto done; error: - res = _Py_INIT_ERR("can't initialize sys standard streams"); + res = _PyStatus_ERR("can't initialize sys standard streams"); done: _Py_ClearStandardStreamEncoding(); @@ -2183,16 +2148,16 @@ Py_FatalError(const char *msg) } void _Py_NO_RETURN -_Py_ExitInitError(_PyInitError err) +Py_ExitStatusException(PyStatus status) { - if (_Py_INIT_IS_EXIT(err)) { - exit(err.exitcode); + if (_PyStatus_IS_EXIT(status)) { + exit(status.exitcode); } - else if (_Py_INIT_IS_ERROR(err)) { - fatal_error(err._func, err.err_msg, 1); + else if (_PyStatus_IS_ERROR(status)) { + fatal_error(status.func, status.err_msg, 1); } else { - Py_FatalError("_Py_ExitInitError() must not be called on success"); + Py_FatalError("Py_ExitStatusException() must not be called on success"); } } @@ -2284,7 +2249,7 @@ Py_Exit(int sts) exit(sts); } -static _PyInitError +static PyStatus init_signals(void) { #ifdef SIGPIPE @@ -2298,9 +2263,9 @@ init_signals(void) #endif PyOS_InitInterrupts(); /* May imply initsignal() */ if (PyErr_Occurred()) { - return _Py_INIT_ERR("can't import signal"); + return _PyStatus_ERR("can't import signal"); } - return _Py_INIT_OK(); + return _PyStatus_OK(); } diff --git a/Python/pystate.c b/Python/pystate.c index 41c6622..d1a8d24 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -3,7 +3,7 @@ #include "Python.h" #include "pycore_ceval.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_pymem.h" #include "pycore_pystate.h" #include "pycore_pylifecycle.h" @@ -42,7 +42,7 @@ static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_st static void _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate); -static _PyInitError +static PyStatus _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) { /* We preserve the hook across init, because there is @@ -60,7 +60,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) _PyGC_Initialize(&runtime->gc); _PyEval_Initialize(&runtime->ceval); - _PyPreConfig_InitPythonConfig(&runtime->preconfig); + PyPreConfig_InitPythonConfig(&runtime->preconfig); runtime->gilstate.check_enabled = 1; @@ -71,22 +71,22 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) runtime->interpreters.mutex = PyThread_allocate_lock(); if (runtime->interpreters.mutex == NULL) { - return _Py_INIT_ERR("Can't initialize threads for interpreter"); + return _PyStatus_ERR("Can't initialize threads for interpreter"); } runtime->interpreters.next_id = -1; runtime->xidregistry.mutex = PyThread_allocate_lock(); if (runtime->xidregistry.mutex == NULL) { - return _Py_INIT_ERR("Can't initialize threads for cross-interpreter data registry"); + return _PyStatus_ERR("Can't initialize threads for cross-interpreter data registry"); } // Set it to the ID of the main thread of the main interpreter. runtime->main_thread = PyThread_get_thread_ident(); - return _Py_INIT_OK(); + return _PyStatus_OK(); } -_PyInitError +PyStatus _PyRuntimeState_Init(_PyRuntimeState *runtime) { /* Force default allocator, since _PyRuntimeState_Fini() must @@ -94,10 +94,10 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyInitError err = _PyRuntimeState_Init_impl(runtime); + PyStatus status = _PyRuntimeState_Init_impl(runtime); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return err; + return status; } void @@ -163,7 +163,7 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) static void _PyGILState_NoteThreadState( struct _gilstate_runtime_state *gilstate, PyThreadState* tstate); -_PyInitError +PyStatus _PyInterpreterState_Enable(_PyRuntimeState *runtime) { struct pyinterpreters *interpreters = &runtime->interpreters; @@ -182,11 +182,11 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); if (interpreters->mutex == NULL) { - return _Py_INIT_ERR("Can't initialize threads for interpreter"); + return _PyStatus_ERR("Can't initialize threads for interpreter"); } } - return _Py_INIT_OK(); + return _PyStatus_OK(); } PyInterpreterState * @@ -205,8 +205,11 @@ PyInterpreterState_New(void) interp->id_refcount = -1; interp->check_interval = 100; - _PyInitError err = _PyCoreConfig_InitPythonConfig(&interp->core_config); - if (_Py_INIT_FAILED(err)) { + PyStatus status = PyConfig_InitPythonConfig(&interp->config); + if (_PyStatus_EXCEPTION(status)) { + /* Don't report status to caller: PyConfig_InitPythonConfig() + can only fail with a memory allocation error. */ + PyConfig_Clear(&interp->config); PyMem_RawFree(interp); return NULL; } @@ -269,7 +272,7 @@ _PyInterpreterState_Clear(_PyRuntimeState *runtime, PyInterpreterState *interp) Py_CLEAR(interp->audit_hooks); - _PyCoreConfig_Clear(&interp->core_config); + PyConfig_Clear(&interp->config); Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_error_registry); @@ -523,12 +526,6 @@ _PyInterpreterState_RequireIDRef(PyInterpreterState *interp, int required) interp->requires_idref = required ? 1 : 0; } -_PyCoreConfig * -_PyInterpreterState_GetCoreConfig(PyInterpreterState *interp) -{ - return &interp->core_config; -} - PyObject * _PyInterpreterState_GetMainModule(PyInterpreterState *interp) { @@ -775,7 +772,7 @@ _PyState_ClearModules(void) void PyThreadState_Clear(PyThreadState *tstate) { - int verbose = tstate->interp->core_config.verbose; + int verbose = tstate->interp->config.verbose; if (verbose && tstate->frame != NULL) fprintf(stderr, diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 26cb02a..665c9c9 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -94,7 +94,7 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags * PyCompilerFlags local_flags; int nomem_count = 0; #ifdef Py_REF_DEBUG - int show_ref_count = _PyInterpreterState_Get()->core_config.show_ref_count; + int show_ref_count = _PyInterpreterState_Get()->config.show_ref_count; #endif filename = PyUnicode_DecodeFSDefault(filename_str); @@ -584,7 +584,7 @@ print_error_text(PyObject *f, int offset, PyObject *text_obj) int _Py_HandleSystemExit(int *exitcode_p) { - int inspect = _PyInterpreterState_GET_UNSAFE()->core_config.inspect; + int inspect = _PyInterpreterState_GET_UNSAFE()->config.inspect; if (inspect) { /* Don't exit if -i flag was given. This flag is set to 0 * when entering interactive mode for inspecting. */ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 08a1a29..24018e2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -17,7 +17,7 @@ Data members: #include "Python.h" #include "code.h" #include "frameobject.h" -#include "pycore_coreconfig.h" +#include "pycore_initconfig.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" #include "pycore_pathconfig.h" @@ -752,7 +752,7 @@ sys_getfilesystemencoding_impl(PyObject *module) /*[clinic end generated code: output=1dc4bdbe9be44aa7 input=8475f8649b8c7d8c]*/ { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - const _PyCoreConfig *config = &interp->core_config; + const PyConfig *config = &interp->config; return PyUnicode_FromWideChar(config->filesystem_encoding, -1); } @@ -767,7 +767,7 @@ sys_getfilesystemencodeerrors_impl(PyObject *module) /*[clinic end generated code: output=ba77b36bbf7c96f5 input=22a1e8365566f1e5]*/ { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - const _PyCoreConfig *config = &interp->core_config; + const PyConfig *config = &interp->config; return PyUnicode_FromWideChar(config->filesystem_errors, -1); } @@ -2475,8 +2475,8 @@ make_flags(_PyRuntimeState *runtime, PyInterpreterState *interp) { int pos = 0; PyObject *seq; - const _PyPreConfig *preconfig = &runtime->preconfig; - const _PyCoreConfig *config = &interp->core_config; + const PyPreConfig *preconfig = &runtime->preconfig; + const PyConfig *config = &interp->config; seq = PyStructSequence_New(&FlagsType); if (seq == NULL) @@ -2690,7 +2690,7 @@ static struct PyModuleDef sysmodule = { } \ } while (0) -static _PyInitError +static PyStatus _PySys_InitCore(_PyRuntimeState *runtime, PyInterpreterState *interp, PyObject *sysdict) { @@ -2827,13 +2827,13 @@ _PySys_InitCore(_PyRuntimeState *runtime, PyInterpreterState *interp, if (PyErr_Occurred()) { goto err_occurred; } - return _Py_INIT_OK(); + return _PyStatus_OK(); type_init_failed: - return _Py_INIT_ERR("failed to initialize a type"); + return _PyStatus_ERR("failed to initialize a type"); err_occurred: - return _Py_INIT_ERR("can't initialize sys module"); + return _PyStatus_ERR("can't initialize sys module"); } #undef SET_SYS_FROM_STRING @@ -2885,7 +2885,7 @@ error: static PyObject* -sys_create_xoptions_dict(const _PyCoreConfig *config) +sys_create_xoptions_dict(const PyConfig *config) { Py_ssize_t nxoption = config->xoptions.length; wchar_t * const * xoptions = config->xoptions.items; @@ -2910,12 +2910,12 @@ int _PySys_InitMain(_PyRuntimeState *runtime, PyInterpreterState *interp) { PyObject *sysdict = interp->sysdict; - const _PyCoreConfig *config = &interp->core_config; + const PyConfig *config = &interp->config; int res; #define COPY_LIST(KEY, VALUE) \ do { \ - PyObject *list = _PyWstrList_AsList(&(VALUE)); \ + PyObject *list = _PyWideStringList_AsList(&(VALUE)); \ if (list == NULL) { \ return -1; \ } \ @@ -3003,7 +3003,7 @@ err_occurred: infrastructure for the io module in place. Use UTF-8/surrogateescape and ignore EAGAIN errors. */ -_PyInitError +PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict) { PyObject *pstderr = PyFile_NewStdPrinter(fileno(stderr)); @@ -3017,56 +3017,56 @@ _PySys_SetPreliminaryStderr(PyObject *sysdict) goto error; } Py_DECREF(pstderr); - return _Py_INIT_OK(); + return _PyStatus_OK(); error: Py_XDECREF(pstderr); - return _Py_INIT_ERR("can't set preliminary stderr"); + return _PyStatus_ERR("can't set preliminary stderr"); } /* Create sys module without all attributes: _PySys_InitMain() should be called later to add remaining attributes. */ -_PyInitError +PyStatus _PySys_Create(_PyRuntimeState *runtime, PyInterpreterState *interp, PyObject **sysmod_p) { PyObject *modules = PyDict_New(); if (modules == NULL) { - return _Py_INIT_ERR("can't make modules dictionary"); + return _PyStatus_ERR("can't make modules dictionary"); } interp->modules = modules; PyObject *sysmod = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION); if (sysmod == NULL) { - return _Py_INIT_ERR("failed to create a module object"); + return _PyStatus_ERR("failed to create a module object"); } PyObject *sysdict = PyModule_GetDict(sysmod); if (sysdict == NULL) { - return _Py_INIT_ERR("can't initialize sys dict"); + return _PyStatus_ERR("can't initialize sys dict"); } Py_INCREF(sysdict); interp->sysdict = sysdict; if (PyDict_SetItemString(sysdict, "modules", interp->modules) < 0) { - return _Py_INIT_ERR("can't initialize sys module"); + return _PyStatus_ERR("can't initialize sys module"); } - _PyInitError err = _PySys_SetPreliminaryStderr(sysdict); - if (_Py_INIT_FAILED(err)) { - return err; + PyStatus status = _PySys_SetPreliminaryStderr(sysdict); + if (_PyStatus_EXCEPTION(status)) { + return status; } - err = _PySys_InitCore(runtime, interp, sysdict); - if (_Py_INIT_FAILED(err)) { - return err; + status = _PySys_InitCore(runtime, interp, sysdict); + if (_PyStatus_EXCEPTION(status)) { + return status; } _PyImport_FixupBuiltin(sysmod, "sys", interp->modules); *sysmod_p = sysmod; - return _Py_INIT_OK(); + return _PyStatus_OK(); } @@ -3156,7 +3156,7 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) if (updatepath) { /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path. If argv[0] is a symlink, use the real path. */ - const _PyWstrList argv_list = {.length = argc, .items = argv}; + const PyWideStringList argv_list = {.length = argc, .items = argv}; PyObject *path0 = NULL; if (_PyPathConfig_ComputeSysPath0(&argv_list, &path0)) { if (path0 == NULL) { -- cgit v0.12