Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
ba99f2e
Make _contextvars a builtin module.
nascheme Dec 28, 2024
6d00c2a
Add 'context' parameter to Thread.
nascheme Dec 21, 2024
a868fe9
Tweak blurb markup.
nascheme Feb 7, 2025
16fa2c3
Doc markup fix.
nascheme Feb 7, 2025
f0ccc8d
Use contextvar for catch_warnings().
nascheme Dec 27, 2024
bcadd20
Add blurb.
nascheme Feb 11, 2025
0cfe578
Add "_warnings_context" as identifier.
nascheme Feb 11, 2025
928c2df
Fix test_support for context var filters.
nascheme Feb 11, 2025
65751d9
Regenerate 'configure' script.
nascheme Feb 11, 2025
09e72b8
Rename flag to `thread_inherit_context`.
nascheme Feb 11, 2025
75f1b38
Merge branch 'main' into thread_inherit_context
nascheme Feb 11, 2025
872920d
Regenerate 'configure' script.
nascheme Feb 11, 2025
5b6b59e
Merge branch 'thread_inherit_context' into gh-128384-warnings-contextvar
nascheme Feb 11, 2025
9e955dc
Use separate flag `thread_safe_warnings`.
nascheme Feb 12, 2025
3a56c64
Add doc for ``thread_safe_warnings`` flag.
nascheme Feb 12, 2025
daa3d52
Create _py_warnings.py for Python implementation.
nascheme Feb 18, 2025
83419e4
Add _warnings_context to _warnings module.
nascheme Feb 18, 2025
15443e8
Remove '_warnings_context' global string.
nascheme Feb 18, 2025
983e7ee
Rename flag to 'context_aware_warnings'.
nascheme Feb 18, 2025
e5e660c
Use catch_warnings() for module under test.
nascheme Feb 18, 2025
e054a57
Don't pass 'module' to catch_warnings().
nascheme Feb 18, 2025
2466cec
Correct error in warnings module docs.
nascheme Feb 19, 2025
165a573
Use PyObject_GetAttr.
nascheme Feb 19, 2025
af8728d
Typo fix for docstring.
nascheme Feb 19, 2025
1c02b7e
Avoid DECREF calls on None.
nascheme Feb 19, 2025
dba89e0
Add warnings.py module (missed in previous commit).
nascheme Feb 19, 2025
2c48fc5
Add comment about why 'context' is passed in test.
nascheme Feb 19, 2025
53eb72d
Revise "decimal' docs, adding note about flag.
nascheme Feb 21, 2025
9cb6f73
Merge branch 'thread_inherit_context' into gh-128384-warnings-contextvar
nascheme Feb 21, 2025
f79daaa
Fix race in filter_search().
nascheme Feb 25, 2025
5ca1d39
Add note to free-threading howto.
nascheme Mar 11, 2025
9420a9d
Merge branch 'main' into gh-128384-warnings-contextvar
nascheme Mar 11, 2025
bad0fdb
Doc fixes for missing refs.
nascheme Mar 12, 2025
bb35c2e
Add "_py_warnings" to stdlib_module_names.h.
nascheme Mar 12, 2025
adf32cb
Improve error text in Python/_warnings.c
nascheme Mar 17, 2025
47d0b6f
Avoid unused-variable warning in _warnings.c.
nascheme Mar 17, 2025
b880dd1
Minor code improvement to _warnings.c.
nascheme Mar 17, 2025
5a1115b
Merge 'origin/main' into gh-128384-warnings-contextvar
nascheme Mar 17, 2025
ae701e3
Merge branch 'origin/main' into gh-128384-warnings-contextvar
nascheme Mar 18, 2025
153c6b1
Merge 'origin/main' into gh-128384-warnings-contextvar
nascheme Mar 26, 2025
9220223
Add extra unit tests.
nascheme Mar 27, 2025
c2c90cb
Use asyncio events to get deterministic execution.
nascheme Mar 27, 2025
c1def22
Merge 'origin/main' into gh-128384-warnings-contextvar
nascheme Apr 9, 2025
4e461d9
Add unit test for asyncio tasks.
nascheme Apr 9, 2025
543927b
Update Doc/howto/free-threading-python.rst
nascheme Apr 9, 2025
4f11910
Use asyncio.gather() rather than create_task().
nascheme Apr 9, 2025
42d157b
Call resetwarnings() in a few places.
nascheme Apr 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rename flag to 'context_aware_warnings'.
  • Loading branch information
nascheme committed Feb 18, 2025
commit 983e7ee7272244de3ff8d4e2415ee7e37dccd5a2
6 changes: 3 additions & 3 deletions Doc/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -602,9 +602,9 @@ always available. Unless explicitly noted otherwise, all variables are read-only
- :option:`-X thread_inherit_context <-X>` and
:envvar:`PYTHON_THREAD_INHERIT_CONTEXT`

* - .. attribute:: flags.thread_safe_warnings
* - .. attribute:: flags.context_aware_warnings
- :option:`-X thread_inherit_context <-X>` and
:envvar:`PYTHON_THREAD_SAFE_WARNINGS`
:envvar:`PYTHON_CONTEXT_AWARE_WARNINGS`


.. versionchanged:: 3.2
Expand Down Expand Up @@ -640,7 +640,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only
Added the ``thread_inherit_context`` attribute.

.. versionchanged:: 3.14
Added the ``thread_safe_warnings`` attribute.
Added the ``context_aware_warnings`` attribute.


.. data:: float_info
Expand Down
54 changes: 29 additions & 25 deletions Doc/library/warnings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ of deprecated code.

.. note::

See :ref:`warning-thread-safe` for details on the thread-safety of the
:class:`catch_warnings` context manager when used in multi-threaded
programs.
See :ref:`warning-concurrent-safe` for details on the
concurrency-safety of the :class:`catch_warnings` context manager when
used in programs using multiple threads or async functions.

.. _warning-testing:

Expand Down Expand Up @@ -370,9 +370,9 @@ results.

.. note::

See :ref:`warning-thread-safe` for details on the thread-safety of the
:class:`catch_warnings` context manager when used in multi-threaded
programs.
See :ref:`warning-concurrent-safe` for details on the
concurrency-safety of the :class:`catch_warnings` context manager when
used in programs using multiple threads or async functions.

When testing multiple operations that raise the same kind of warning, it
is important to test them in a manner that confirms each operation is raising
Expand Down Expand Up @@ -620,31 +620,35 @@ Available Context Managers

.. note::

See :ref:`warning-thread-safe` for details on the thread-safety of the
:class:`catch_warnings` context manager when used in multi-threaded
programs.
See :ref:`warning-concurrent-safe` for details on the
concurrency-safety of the :class:`catch_warnings` context manager when
used in programs using multiple threads or async functions.


.. versionchanged:: 3.11

Added the *action*, *category*, *lineno*, and *append* parameters.


.. _warning-thread-safe:
.. _warning-concurrent-safe:

Thread-safety of Context Managers
---------------------------------
Concurrent safety of Context Managers
-------------------------------------

The behavior of :class:`catch_warnings` context manager depends on the value
of the :data:`sys.flags.thread_safe_warnings` flag. If the flag is true, the
context manager behaves in a thread-safe fashion and otherwise not. Being
thread-safe means that behavior is predictable in a multi-threaded program.
For free-threaded builds, the flag defaults to true, and false otherwise.
The behavior of :class:`catch_warnings` context manager depends on the
:data:`sys.flags.context_aware_warnings` flag. If the flag is true, the
context manager behaves in a concurrent-safe fashion and otherwise not.
Concurrent-safe means that it is both thread-safe and safe to use within
:ref:`asyncio coroutines <coroutine>` and tasks. Being thread-safe means
that behavior is predictable in a multi-threaded program. The flag defaults
to true for free-threaded builds and false otherwise.

If the :data:`~sys.flags.thread_safe_warnings` flag is false, then
If the :data:`~sys.flags.context_aware_warnings` flag is false, then
:class:`catch_warnings` will modify the global attributes of the
:mod:`warnings` module. This is not thread-safe. If two or more threads use
the context manager at the same time, the behavior is undefined.
:mod:`warnings` module. This is not safe if used within a concurrent program
(using multiple threads or using asyncio coroutines). For example, if two
or more threads use the :class:`catch_warnings` class at the same time, the
behavior is undefined.

If the flag is true, :class:`catch_warnings` will not modify global
attributes and will instead use a :class:`~contextvars.ContextVar` to
Expand All @@ -655,16 +659,16 @@ thread-safe.
The *record* parameter of the context handler also behaves differently
depending on the value of the flag. When *record* is true and the flag is
false, the context manager works by replacing and then later restoring the
module's :func:`showwarning` function. This is not thread-safe.
module's :func:`showwarning` function. That is not concurrent-safe.

When *record* is true and the flag is false, the :func:`showwarning` function
is not replaced. The recording status is instead indicated by an internal
property in the context variable. In this case, the :func:`showwarning`
function will not be restored when exiting the context handler.

The :data:`~sys.flags.thread_safe_warnings` flag can be set the :option:`-X
thread_safe_warnings<-X>` command-line option or by the
:envvar:`PYTHON_THREAD_SAFE_WARNINGS` environment variable.
The :data:`~sys.flags.context_aware_warnings` flag can be set the :option:`-X
context_aware_warnings<-X>` command-line option or by the
:envvar:`PYTHON_CONTEXT_AWARE_WARNINGS` environment variable.

.. note::

Expand All @@ -681,6 +685,6 @@ thread_safe_warnings<-X>` command-line option or by the

.. versionchanged:: 3.14

Added the :data:`sys.flags.thread_safe_warnings` flag and the use of a
Added the :data:`sys.flags.context_aware_warnings` flag and the use of a
context variable for :class:`catch_warnings` if the flag is true. Previous
versions of Python acted as if the flag was always set to false.
8 changes: 4 additions & 4 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,11 @@ Miscellaneous options

.. versionadded:: 3.14

* :samp:`-X thread_safe_warnings={0,1}` causes the
* :samp:`-X context_aware_warnings={0,1}` causes the
:class:`warnings.catch_warnings` context manager to use a
:class:`~contextvars.ContextVar` to store warnings filter state. If
unset, the value of this option defaults to ``1`` on free-threaded builds
and to ``0`` otherwise. See also :envvar:`PYTHON_THREAD_SAFE_WARNINGS`.
and to ``0`` otherwise. See also :envvar:`PYTHON_CONTEXT_AWARE_WARNINGS`.

.. versionadded:: 3.14

Expand Down Expand Up @@ -1248,13 +1248,13 @@ conflict.

.. versionadded:: 3.14

.. envvar:: PYTHON_THREAD_SAFE_WARNINGS
.. envvar:: PYTHON_CONTEXT_AWARE_WARNINGS

If set to ``1`` then the :class:`warnings.catch_warnings` context
manager will use a :class:`~contextvars.ContextVar` to store warnings
filter state. If unset, this variable defaults to ``1`` on
free-threaded builds and to ``0`` otherwise. See :option:`-X
thread_safe_warnings<-X>`.
context_aware_warnings<-X>`.

.. versionadded:: 3.14

Expand Down
2 changes: 1 addition & 1 deletion Include/cpython/initconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ typedef struct PyConfig {
int safe_path;
int int_max_str_digits;
int thread_inherit_context;
int thread_safe_warnings;
int context_aware_warnings;
#ifdef __APPLE__
int use_system_logger;
#endif
Expand Down
2 changes: 1 addition & 1 deletion Lib/_py_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def _set_module(module):
# If true, catch_warnings() will use a context var to hold the modified
# filters list. Otherwise, catch_warnings() will operate on the 'filters'
# global of the warnings module.
_use_context = sys.flags.thread_safe_warnings
_use_context = sys.flags.context_aware_warnings


class _Context:
Expand Down
6 changes: 3 additions & 3 deletions Lib/test/test_capi/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def test_config_get(self):
("hash_seed", int, None),
("home", str | None, None),
("thread_inherit_context", int, None),
("thread_safe_warnings", int, None),
("context_aware_warnings", int, None),
("import_time", bool, None),
("inspect", bool, None),
("install_signal_handlers", bool, None),
Expand Down Expand Up @@ -172,7 +172,7 @@ def test_config_get_sys_flags(self):
("warn_default_encoding", "warn_default_encoding", False),
("safe_path", "safe_path", False),
("int_max_str_digits", "int_max_str_digits", False),
# "gil", "thread_inherit_context" and "thread_safe_warnings" are tested below
# "gil", "thread_inherit_context" and "context_aware_warnings" are tested below
):
with self.subTest(flag=flag, name=name, negate=negate):
value = config_get(name)
Expand All @@ -193,7 +193,7 @@ def test_config_get_sys_flags(self):
self.assertEqual(sys.flags.thread_inherit_context, expected_inherit_context)

expected_safe_warnings = 1 if support.Py_GIL_DISABLED else 0
self.assertEqual(sys.flags.thread_safe_warnings, expected_safe_warnings)
self.assertEqual(sys.flags.context_aware_warnings, expected_safe_warnings)

def test_config_get_non_existent(self):
# Test PyConfig_Get() on non-existent option name
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
f'{VERSION_MINOR}{ABI_THREAD}/lib-dynload')

DEFAULT_THREAD_INHERIT_CONTEXT = 1 if support.Py_GIL_DISABLED else 0
DEFAULT_THREAD_SAFE_WARNINGS = 1 if support.Py_GIL_DISABLED else 0
DEFAULT_CONTEXT_AWARE_WARNINGS = 1 if support.Py_GIL_DISABLED else 0

# If we are running from a build dir, but the stdlib has been installed,
# some tests need to expect different results.
Expand Down Expand Up @@ -589,7 +589,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'perf_profiling': 0,
'import_time': False,
'thread_inherit_context': DEFAULT_THREAD_INHERIT_CONTEXT,
'thread_safe_warnings': DEFAULT_THREAD_SAFE_WARNINGS,
'context_aware_warnings': DEFAULT_CONTEXT_AWARE_WARNINGS,
'code_debug_ranges': True,
'show_ref_count': False,
'dump_refs': False,
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -1846,7 +1846,7 @@ def test_pythontypes(self):
# XXX
# sys.flags
# FIXME: The +3 is for the 'gil', 'thread_inherit_context' and
# 'thread_safe_warnings' flags and will not be necessary once
# 'context_aware_warnings' flags and will not be necessary once
# gh-122575 is fixed
check(sys.flags, vsize('') + self.P * (3 + len(sys.flags)))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Make :class:`warnings.catch_warnings` use a context variable for holding
the warning filtering state if the :data:`sys.flags.thread_safe_warnings`
the warning filtering state if the :data:`sys.flags.context_aware_warnings`
flag is set to true. This makes using the context manager thread-safe in
multi-threaded programs. The flag is true by default in free-threaded builds
and is otherwise false. The value of the flag can be overridden by the
the :option:`-X thread_safe_warnings <-X>` command-line option or by the
:envvar:`PYTHON_THREAD_SAFE_WARNINGS` environment variable.
the :option:`-X context_aware_warnings <-X>` command-line option or by the
:envvar:`PYTHON_CONTEXT_AWARE_WARNINGS` environment variable.
43 changes: 21 additions & 22 deletions Python/initconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
SPEC(hash_seed, ULONG, READ_ONLY, NO_SYS),
SPEC(home, WSTR_OPT, READ_ONLY, NO_SYS),
SPEC(thread_inherit_context, INT, READ_ONLY, NO_SYS),
SPEC(thread_safe_warnings, INT, READ_ONLY, NO_SYS),
SPEC(context_aware_warnings, INT, READ_ONLY, NO_SYS),
SPEC(import_time, BOOL, READ_ONLY, NO_SYS),
SPEC(install_signal_handlers, BOOL, READ_ONLY, NO_SYS),
SPEC(isolated, BOOL, READ_ONLY, NO_SYS), // sys.flags.isolated
Expand Down Expand Up @@ -330,12 +330,11 @@ The following implementation-specific options are available:\n\
-X thread_inherit_context=[0|1]: enable (1) or disable (0) threads inheriting\n\
context vars by default; enabled by default in the free-threaded\n\
build and disabled otherwise; also PYTHON_THREAD_INHERIT_CONTEXT\n\
-X thread_safe_warnings=[0|1]: if true (1) then the warnings module will\n\
use a context variable to store warnings filtering state, making it\n\
safe to use in multi-threaded programs; if false (0) then the\n\
warnings module will use module globals, which is not thread-safe;\n\
set to true for free-threaded builds and false otherwise; also\n\
PYTHON_THREAD_SAFE_WARNINGS\n\
-X context_aware_warnings=[0|1]: if true (1) then the warnings module will\n\
use a context variables; if false (0) then the warnings module will\n\
use module globals, which is not concurrent-safe; set to true for\n\
free-threaded builds and false otherwise; also\n\
PYTHON_CONTEXT_AWARE_WARNINGS\n\
-X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n \
of N frames (default: 1); also PYTHONTRACEMALLOC=N\n\
-X utf8[=0|1]: enable (1) or disable (0) UTF-8 mode; also PYTHONUTF8\n\
Expand Down Expand Up @@ -425,8 +424,8 @@ static const char usage_envvars[] =
#endif
"PYTHON_THREAD_INHERIT_CONTEXT: if true (1), threads inherit context vars\n"
" (-X thread_inherit_context)\n"
"PYTHON_THREAD_SAFE_WARNINGS: if true (1), enable thread-safe warnings module\n"
" behaviour (-X thread_safe_warnings)\n"
"PYTHON_CONTEXT_AWARE_WARNINGS: if true (1), enable thread-safe warnings module\n"
" behaviour (-X context_aware_warnings)\n"
"PYTHONTRACEMALLOC: trace Python memory allocations (-X tracemalloc)\n"
"PYTHONUNBUFFERED: disable stdout/stderr buffering (-u)\n"
"PYTHONUTF8 : control the UTF-8 mode (-X utf8)\n"
Expand Down Expand Up @@ -903,7 +902,7 @@ config_check_consistency(const PyConfig *config)
// config->use_frozen_modules is initialized later
// by _PyConfig_InitImportConfig().
assert(config->thread_inherit_context >= 0);
assert(config->thread_safe_warnings >= 0);
assert(config->context_aware_warnings >= 0);
#ifdef __APPLE__
assert(config->use_system_logger >= 0);
#endif
Expand Down Expand Up @@ -1011,10 +1010,10 @@ _PyConfig_InitCompatConfig(PyConfig *config)
config->cpu_count = -1;
#ifdef Py_GIL_DISABLED
config->thread_inherit_context = 1;
config->thread_safe_warnings = 1;
config->context_aware_warnings = 1;
#else
config->thread_inherit_context = 0;
config->thread_safe_warnings = 0;
config->context_aware_warnings = 0;
#endif
#ifdef __APPLE__
config->use_system_logger = 0;
Expand Down Expand Up @@ -1050,10 +1049,10 @@ config_init_defaults(PyConfig *config)
#endif
#ifdef Py_GIL_DISABLED
config->thread_inherit_context = 1;
config->thread_safe_warnings = 1;
config->context_aware_warnings = 1;
#else
config->thread_inherit_context = 0;
config->thread_safe_warnings = 0;
config->context_aware_warnings = 0;
#endif
#ifdef __APPLE__
config->use_system_logger = 0;
Expand Down Expand Up @@ -1950,27 +1949,27 @@ config_init_thread_inherit_context(PyConfig *config)
}

static PyStatus
config_init_thread_safe_warnings(PyConfig *config)
config_init_context_aware_warnings(PyConfig *config)
{
const char *env = config_get_env(config, "PYTHON_THREAD_SAFE_WARNINGS");
const char *env = config_get_env(config, "PYTHON_CONTEXT_AWARE_WARNINGS");
if (env) {
int enabled;
if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
return _PyStatus_ERR(
"PYTHON_THREAD_SAFE_WARNINGS=N: N is missing or invalid");
"PYTHON_CONTEXT_AWARE_WARNINGS=N: N is missing or invalid");
}
config->thread_safe_warnings = enabled;
config->context_aware_warnings = enabled;
}

const wchar_t *xoption = config_get_xoption(config, L"thread_safe_warnings");
const wchar_t *xoption = config_get_xoption(config, L"context_aware_warnings");
if (xoption) {
int enabled;
const wchar_t *sep = wcschr(xoption, L'=');
if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
return _PyStatus_ERR(
"-X thread_safe_warnings=n: n is missing or invalid");
"-X context_aware_warnings=n: n is missing or invalid");
}
config->thread_safe_warnings = enabled;
config->context_aware_warnings = enabled;
}
return _PyStatus_OK();
}
Expand Down Expand Up @@ -2259,7 +2258,7 @@ config_read_complex_options(PyConfig *config)
return status;
}

status = config_init_thread_safe_warnings(config);
status = config_init_context_aware_warnings(config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
Expand Down
4 changes: 2 additions & 2 deletions Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3142,7 +3142,7 @@ static PyStructSequence_Field flags_fields[] = {
{"int_max_str_digits", "-X int_max_str_digits"},
{"gil", "-X gil"},
{"thread_inherit_context", "-X thread_inherit_context"},
{"thread_safe_warnings", "-X thread_safe_warnings"},
{"context_aware_warnings", "-X context_aware_warnings"},
{0}
};

Expand Down Expand Up @@ -3247,7 +3247,7 @@ set_flags_from_config(PyInterpreterState *interp, PyObject *flags)
SetFlagObj(PyLong_FromLong(1));
#endif
SetFlag(config->thread_inherit_context);
SetFlag(config->thread_safe_warnings);
SetFlag(config->context_aware_warnings);
#undef SetFlagObj
#undef SetFlag
return 0;
Expand Down