PEP 741: Add sys.set_config() (#3709)
This commit is contained in:
parent
c4a5976ff3
commit
66ecf110b0
|
@ -16,8 +16,10 @@ Add a C API to the limited C API to configure the Python initialization,
|
|||
and to get the current configuration. It can be used with the stable
|
||||
ABI.
|
||||
|
||||
Add also ``sys.get_config(name)`` and ``sys.get_config_names()``
|
||||
functions to get the current configuration.
|
||||
Add ``sys.get_config(name)`` and ``sys.get_config_names()`` functions to
|
||||
get the current configuration. Add ``sys.set_config(name, value)``
|
||||
function to set a configuration option. Unified API to access all
|
||||
configuration options.
|
||||
|
||||
Complete :pep:`587` API by adding ``PyInitConfig_AddModule()`` which can be
|
||||
used to add a built-in extension module; feature previously referred to
|
||||
|
@ -120,7 +122,7 @@ Cython needs to access the ``optimization_level`` configuration option:
|
|||
|
||||
When global configuration variables were deprecated in 2022, `Marc-André
|
||||
Lemburg requested
|
||||
<https://github.com/python/cpython/issues/93103#issuecomment-1136462708>`_
|
||||
<https://github.com/python/cpython/issues/93103#issuecomment-1136462708>`__
|
||||
an API to access these configuration variables at runtime (not only
|
||||
during Python initialization).
|
||||
|
||||
|
@ -359,6 +361,35 @@ which doesn't take in account environment variables.
|
|||
The ``sys.get_int_max_str_digits()`` function can be used to get the
|
||||
``int_max_str_digits`` option.
|
||||
|
||||
Set the current configuration
|
||||
-----------------------------
|
||||
|
||||
`Marc-André Lemburg requested
|
||||
<https://discuss.python.org/t/fr-allow-private-runtime-config-to-enable-extending-without-breaking-the-pyconfig-abi/18004/34>`__
|
||||
an API to **set** the value of some configuration options at runtime:
|
||||
|
||||
* ``optimization_level``
|
||||
* ``verbose``
|
||||
* ``parser_debug``
|
||||
* ``inspect``
|
||||
* ``write_bytecode``
|
||||
|
||||
Moreover, currently, when a new configuration option is added, usually
|
||||
"get" and "set" functions should be added as well. It makes the ``sys``
|
||||
module bigger and bigger, whereas not all options deserves dedicated
|
||||
functions. For example, when the ``int_max_str_digits`` option was
|
||||
added, ``sys.get_int_max_str_digits()`` and
|
||||
``sys.set_int_max_str_digits()`` functions were added as well.
|
||||
|
||||
Some options are exposed directly as ``sys`` attributes. For example,
|
||||
the ``module_search_paths`` option is expoed as ``sys.path``. The
|
||||
problem is that there is no validation when the attribute is modified
|
||||
which can lead to various bugs or even crashes. The attribute can even
|
||||
be removed: ``del sys.path``.
|
||||
|
||||
Having a single unified API with generic "get" and "set" functions would
|
||||
avoid these issues and give access to all configuration options.
|
||||
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
@ -394,9 +425,11 @@ Add C API and Python functions to get the current configuration:
|
|||
|
||||
* ``PyConfig_Get(name)``.
|
||||
* ``PyConfig_GetInt(name, &value)``.
|
||||
* ``PyConfig_Set(name)``.
|
||||
* ``PyConfig_Keys()``.
|
||||
* ``sys.get_config(name)``.
|
||||
* ``sys.get_config_names()``.
|
||||
* ``sys.set_config(name, value)``.
|
||||
|
||||
The C API uses null-terminated UTF-8 encoded strings to refer to a
|
||||
configuration option.
|
||||
|
@ -419,82 +452,8 @@ The ``PyStatus`` status is no longer separated, but part of the unified
|
|||
Configuration Options
|
||||
---------------------
|
||||
|
||||
Configuration option names:
|
||||
|
||||
* ``"allocator"`` (integer)
|
||||
* ``"argv"`` (string list).
|
||||
* ``"base_exec_prefix"`` (string).
|
||||
* ``"base_executable"`` (string).
|
||||
* ``"base_prefix"`` (string).
|
||||
* ``"buffered_stdio"`` (integer).
|
||||
* ``"bytes_warning"`` (integer).
|
||||
* ``"check_hash_pycs_mode"`` (string).
|
||||
* ``"code_debug_ranges"`` (integer).
|
||||
* ``"coerce_c_locale"`` (integer)
|
||||
* ``"coerce_c_locale_warn"`` (integer)
|
||||
* ``"configure_c_stdio"`` (integer).
|
||||
* ``"configure_locale"`` (integer)
|
||||
* ``"cpu_count"`` (integer).
|
||||
* ``"dev_mode"`` (integer).
|
||||
* ``"dump_refs"`` (integer).
|
||||
* ``"dump_refs_file"`` (string).
|
||||
* ``"exec_prefix"`` (string).
|
||||
* ``"executable"`` (string).
|
||||
* ``"faulthandler"`` (integer).
|
||||
* ``"filesystem_encoding"`` (string).
|
||||
* ``"filesystem_errors"`` (string).
|
||||
* ``"hash_seed"`` (unsigned long).
|
||||
* ``"home"`` (string).
|
||||
* ``"import_time"`` (integer).
|
||||
* ``"inspect"`` (integer).
|
||||
* ``"install_signal_handlers"`` (integer).
|
||||
* ``"int_max_str_digits"`` (integer).
|
||||
* ``"interactive"`` (integer).
|
||||
* ``"isolated"`` (integer).
|
||||
* ``"legacy_windows_fs_encoding"`` (integer)
|
||||
* ``"legacy_windows_stdio"`` (integer): only on Windows.
|
||||
* ``"malloc_stats"`` (integer).
|
||||
* ``"module_search_paths"`` (string list).
|
||||
* ``"module_search_paths_set"`` (integer).
|
||||
* ``"optimization_level"`` (integer).
|
||||
* ``"orig_argv"`` (string list).
|
||||
* ``"parse_argv"`` (integer).
|
||||
* ``"parser_debug"`` (integer).
|
||||
* ``"pathconfig_warnings"`` (integer).
|
||||
* ``"perf_profiling"`` (integer).
|
||||
* ``"platlibdir"`` (string).
|
||||
* ``"prefix"`` (string).
|
||||
* ``"program_name"`` (string).
|
||||
* ``"pycache_prefix"`` (string).
|
||||
* ``"pythonpath_env"`` (string).
|
||||
* ``"quiet"`` (integer).
|
||||
* ``"run_command"`` (string).
|
||||
* ``"run_filename"`` (string).
|
||||
* ``"run_module"`` (string).
|
||||
* ``"run_presite"`` (string): only on a Python debug build.
|
||||
* ``"safe_path"`` (integer).
|
||||
* ``"show_ref_count"`` (integer).
|
||||
* ``"site_import"`` (integer).
|
||||
* ``"skip_source_first_line"`` (integer).
|
||||
* ``"stdio_encoding"`` (string).
|
||||
* ``"stdio_errors"`` (string).
|
||||
* ``"stdlib_dir"`` (string).
|
||||
* ``"sys_path_0"`` (string).
|
||||
* ``"tracemalloc"`` (integer).
|
||||
* ``"use_environment"`` (integer).
|
||||
* ``"use_frozen_modules"`` (integer).
|
||||
* ``"use_hash_seed"`` (integer).
|
||||
* ``"user_site_directory"`` (integer).
|
||||
* ``"utf8_mode"`` (integer)
|
||||
* ``"verbose"`` (integer).
|
||||
* ``"warn_default_encoding"`` (integer).
|
||||
* ``"warnoptions"`` (string list).
|
||||
* ``"write_bytecode"`` (integer).
|
||||
* ``"xoptions"`` (string list).
|
||||
|
||||
Configuration options are named after ``PyPreConfig`` and ``PyConfig``
|
||||
structure members even if ``PyConfig_Get()`` can also get values from
|
||||
the ``sys`` module. See the `PyPreConfig documentation
|
||||
structure members. See the `PyPreConfig documentation
|
||||
<https://docs.python.org/dev/c-api/init_config.html#pypreconfig>`_ and
|
||||
the `PyConfig documentation
|
||||
<https://docs.python.org/dev/c-api/init_config.html#pyconfig>`_.
|
||||
|
@ -502,6 +461,274 @@ the `PyConfig documentation
|
|||
Deprecating and removing configuration options is out of the scope of
|
||||
the PEP and should be discussed on a case by case basis.
|
||||
|
||||
Public configuration options
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Following options can be get by ``sys.get_config()`` and set and
|
||||
``sys.set_config()``.
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Option
|
||||
- Type
|
||||
- Comment
|
||||
* - ``"argv"``
|
||||
- ``list[str]``
|
||||
- API: ``sys.argv`` (``list[str]``).
|
||||
* - ``"base_exec_prefix"``
|
||||
- ``str``
|
||||
- API: ``sys.base_exec_prefix`` (``str``).
|
||||
* - ``"base_executable"``
|
||||
- ``str``
|
||||
- API: ``sys.base_executable`` (``str``).
|
||||
* - ``"base_prefix"``
|
||||
- ``str``
|
||||
- API: ``sys.base_prefix`` (``str``).
|
||||
* - ``"bytes_warning"``
|
||||
- ``int``
|
||||
- API: ``sys.flags.bytes_warning`` (``int``).
|
||||
* - ``"exec_prefix"``
|
||||
- ``str``
|
||||
- API: ``sys.base_prefix`` (``str``).
|
||||
* - ``"executable"``
|
||||
- ``str``
|
||||
- API: ``sys.executable`` (``str``).
|
||||
* - ``"inspect"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.inspect`` (``int``).
|
||||
* - ``"int_max_str_digits"``
|
||||
- ``int``
|
||||
- API: ``sys.flags.int_max_str_digits`` (``int``),
|
||||
``sys.get_int_max_str_digits()`` and
|
||||
``sys.set_int_max_str_digits()``.
|
||||
* - ``"interactive"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.interactive`` (``int``).
|
||||
* - ``"module_search_paths"``
|
||||
- ``list[str]``
|
||||
- API: ``sys.path`` (``list[str]``).
|
||||
* - ``"optimization_level"``
|
||||
- ``int``
|
||||
- API: ``sys.flags.optimize`` (``int``).
|
||||
* - ``"parser_debug"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.debug`` (``int``).
|
||||
* - ``"platlibdir"``
|
||||
- ``str``
|
||||
- API: ``sys.platlibdir`` (``str``).
|
||||
* - ``"prefix"``
|
||||
- ``str``
|
||||
- API: ``sys.base_prefix`` (``str``).
|
||||
* - ``"pycache_prefix"``
|
||||
- ``str``
|
||||
- API: ``sys.pycache_prefix`` (``str``).
|
||||
* - ``"quiet"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.quiet`` (``int``).
|
||||
* - ``"stdlib_dir"``
|
||||
- ``str``
|
||||
- API: ``sys._stdlib_dir`` (``str``).
|
||||
* - ``"use_environment"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.ignore_environment`` (``int``).
|
||||
* - ``"verbose"``
|
||||
- ``int``
|
||||
- API: ``sys.flags.verbose`` (``int``).
|
||||
* - ``"warnoptions"``
|
||||
- ``list[str]``
|
||||
- API: ``sys.warnoptions`` (``list[str]``).
|
||||
* - ``"write_bytecode"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.dont_write_bytecode`` (``int``) and ``sys.dont_write_bytecode`` (``bool``).
|
||||
* - ``"xoptions"``
|
||||
- ``dict[str, str]``
|
||||
- API: ``sys._xoptions`` (``dict[str, str]``).
|
||||
|
||||
Some option names are different than ``sys`` attributes, such as
|
||||
``"optimization_level"`` option and ``sys.flags.optimize`` attribute.
|
||||
``sys.set_config(name, value)`` sets the corresponding ``sys``
|
||||
attribute.
|
||||
|
||||
Read-only configuration options
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Following options can be get ``sys.get_config()``, but cannot be set by
|
||||
``sys.set_config()``.
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Option
|
||||
- Type
|
||||
- Comment
|
||||
* - ``"check_hash_pycs_mode"``
|
||||
- ``str``
|
||||
- API: ``imp.check_hash_pycs_mode`` (``str``).
|
||||
* - ``"code_debug_ranges"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"coerce_c_locale"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"coerce_c_locale_warn"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"configure_locale"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"cpu_count"``
|
||||
- ``int``
|
||||
- API: ``os.cpu_count()`` (``int | None``).
|
||||
* - ``"dev_mode"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.dev_mode`` (``bool``).
|
||||
* - ``"filesystem_encoding"``
|
||||
- ``str``
|
||||
- API: ``sys.getfilesystemencoding()`` (``str``).
|
||||
* - ``"filesystem_errors"``
|
||||
- ``str``
|
||||
- API: ``sys.getfilesystemencodeerrors()`` (``str``).
|
||||
* - ``"import_time"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"isolated"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.isolated`` (``int``).
|
||||
* - ``"legacy_windows_fs_encoding"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"orig_argv"``
|
||||
- ``list[str]``
|
||||
- API: ``sys.orig_argv`` (``list[str]``).
|
||||
* - ``"perf_profiling"``
|
||||
- ``bool``
|
||||
- API: ``sys.is_stack_trampoline_active()``.
|
||||
* - ``"site_import"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.no_site`` (``int``).
|
||||
* - ``"utf8_mode"``
|
||||
- ``bool``
|
||||
-
|
||||
|
||||
Initialization-only configuration options
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Following options are only to initialize Python, are not in
|
||||
``sys.get_config_names()``, and cannot be get with ``sys.get_config()``.
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Option
|
||||
- Type
|
||||
- Comment
|
||||
* - ``"allocator"``
|
||||
- ``int``
|
||||
-
|
||||
* - ``"buffered_stdio"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"configure_c_stdio"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"dump_refs"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"dump_refs_file"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"faulthandler"``
|
||||
- ``bool``
|
||||
- API: ``faulthandler.is_enabled()`` (``bool``).
|
||||
* - ``"hash_seed"``
|
||||
- ``int``
|
||||
-
|
||||
* - ``"home"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"install_signal_handlers"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"legacy_windows_stdio"``
|
||||
- ``bool``
|
||||
- Windows only
|
||||
* - ``"malloc_stats"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"module_search_paths_set"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"pathconfig_warnings"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"parse_argv"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"program_name"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"pythonpath_env"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"run_command"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"run_filename"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"run_module"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"run_presite"``
|
||||
- ``str``
|
||||
- need a debug build.
|
||||
* - ``"safe_path"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"show_ref_count"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"skip_source_first_line"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"stdio_encoding"``
|
||||
- ``str``
|
||||
- API: ``sys.stdin.encoding``, ``sys.stdout.encoding`` and
|
||||
``sys.stderr.encoding`` (``str``).
|
||||
* - ``"stdio_errors"``
|
||||
- ``str``
|
||||
- API: ``sys.stdin.errors``, ``sys.stdout.errors`` and
|
||||
``sys.stderr.errors`` (``str``).
|
||||
* - ``"sys_path_0"``
|
||||
- ``str``
|
||||
-
|
||||
* - ``"tracemalloc"``
|
||||
- ``int``
|
||||
- API: ``tracemalloc.is_tracing()`` (``bool``).
|
||||
* - ``"use_frozen_modules"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"use_hash_seed"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"user_site_directory"``
|
||||
- ``bool``
|
||||
- API: ``sys.flags.no_user_site`` (``int``).
|
||||
* - ``"warn_default_encoding"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"_install_importlib"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"_init_main"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"_is_python_build"``
|
||||
- ``bool``
|
||||
-
|
||||
* - ``"_pystats"``
|
||||
- ``bool``
|
||||
- API: ``sys._stats_on()``, ``sys._stats_off()``.
|
||||
Need a ``Py_STATS`` build.
|
||||
|
||||
|
||||
Preconfiguration
|
||||
----------------
|
||||
|
@ -732,12 +959,17 @@ Error handling
|
|||
error message.
|
||||
|
||||
|
||||
Get current configuration
|
||||
-------------------------
|
||||
Get and set the current configuration
|
||||
-------------------------------------
|
||||
|
||||
The configuration option *name* parameter must be a non-NULL
|
||||
null-terminated UTF-8 encoded string.
|
||||
|
||||
Not all configuration options are accessible at runtime: see
|
||||
`Configuration Options`_. For example, ``"module_search_paths_set"`` is
|
||||
not relevant and cannot be accessed. Some options are read-only and can
|
||||
only be read, such as ``"utf8_mode"``.
|
||||
|
||||
``PyObject* PyConfig_Get(const char *name)``:
|
||||
Get the current value of a configuration option as an object.
|
||||
|
||||
|
@ -783,22 +1015,33 @@ null-terminated UTF-8 encoded string.
|
|||
|
||||
The caller must hold the GIL.
|
||||
|
||||
``PyObject* PyConfig_Set(const char *name, PyObject *value)``:
|
||||
Set the value of a configuration option.
|
||||
|
||||
sys.get_config()
|
||||
----------------
|
||||
* Raise a ``ValueError`` if there is no option *name*.
|
||||
* Raise a ``TypeError`` if *value* has not the proper type.
|
||||
* Raise a ``ValueError`` if *value* is an invalid value.
|
||||
* Raise a ``ValueError`` if the option is read-only: cannot be set.
|
||||
|
||||
Add ``sys.get_config(name: str)`` function which calls
|
||||
``PyConfig_Get()``:
|
||||
|
||||
* Return the configuration option value on success.
|
||||
* Raise an exception on error.
|
||||
The caller must hold the GIL. The function cannot be called before
|
||||
Python initialization nor after Python finalization.
|
||||
|
||||
|
||||
sys.get_config_names()
|
||||
----------------------
|
||||
Add sys functions
|
||||
-----------------
|
||||
|
||||
* Add ``sys.get_config(name: str)`` function which calls
|
||||
``PyConfig_Get()``:
|
||||
|
||||
* Return the configuration option value on success.
|
||||
* Raise an exception on error.
|
||||
|
||||
* Add ``sys.get_config_names()`` function which gets all configuration
|
||||
option names as a ``frozenset``.
|
||||
|
||||
* Add ``sys.get_config(name: str, value)`` function which calls
|
||||
``PyConfig_Set(name, value)``. Raise an exception on error.
|
||||
|
||||
Add ``sys.get_config_names()`` function which gets all configuration
|
||||
option names as a ``frozenset``.
|
||||
|
||||
Scope of the stable ABI
|
||||
-----------------------
|
||||
|
|
Loading…
Reference in New Issue