From 5d1e78f7b59ffa3308755b5b2e0f85eb0c6ac890 Mon Sep 17 00:00:00 2001 From: Duane Hilton Date: Sat, 27 Dec 2025 00:23:57 -0700 Subject: [PATCH 1/4] gh-143181: Fix 'overriden' -> 'overridden' in c-api/module.rst (#143182) * Doc: Fix typo 'overriden' -> 'overridden' in c-api/module.rst * Fix 'overriden' -> 'overridden' in tests --- Doc/c-api/module.rst | 2 +- Lib/test/test_build_details.py | 2 +- Lib/test/test_dict.py | 2 +- Lib/test/test_set.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 22f8b1309aa38b..37c92aeb6dcb38 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -571,7 +571,7 @@ A module's token -- and the *your_token* value to use in the above code -- is: of that slot; - For modules created from an ``PyModExport_*`` :ref:`export hook `: the slots array that the export - hook returned (unless overriden with :c:macro:`Py_mod_token`). + hook returned (unless overridden with :c:macro:`Py_mod_token`). .. c:macro:: Py_mod_token diff --git a/Lib/test/test_build_details.py b/Lib/test/test_build_details.py index ba9afe69ba46e8..30d9c213077ab7 100644 --- a/Lib/test/test_build_details.py +++ b/Lib/test/test_build_details.py @@ -33,7 +33,7 @@ class FormatTestsBase: @property def contents(self): - """Install details file contents. Should be overriden by subclasses.""" + """Install details file contents. Should be overridden by subclasses.""" raise NotImplementedError @property diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 665b3e843dd3a5..77a5f2a108d07f 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1581,7 +1581,7 @@ def check_unhashable_key(): with check_unhashable_key(): d.get(key) - # Only TypeError exception is overriden, + # Only TypeError exception is overridden, # other exceptions are left unchanged. class HashError: def __hash__(self): diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index c0df9507bd7f5e..203a231201c669 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -661,7 +661,7 @@ def check_unhashable_element(): with check_unhashable_element(): myset.discard(elem) - # Only TypeError exception is overriden, + # Only TypeError exception is overridden, # other exceptions are left unchanged. class HashError: def __hash__(self): From 57d569942c6becad85919e3b7fef5f6136c413b0 Mon Sep 17 00:00:00 2001 From: SYan212 Date: Sat, 27 Dec 2025 07:52:28 +0000 Subject: [PATCH 2/4] Fix typos in docs (#143193) --- Doc/library/linecache.rst | 2 +- Doc/tools/extensions/grammar_snippet.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/linecache.rst b/Doc/library/linecache.rst index e766a9280946d3..07305a2a39b252 100644 --- a/Doc/library/linecache.rst +++ b/Doc/library/linecache.rst @@ -31,7 +31,7 @@ The :mod:`linecache` module defines the following functions: .. index:: triple: module; search; path If *filename* indicates a frozen module (starting with ``' Date: Sat, 27 Dec 2025 19:33:56 +0900 Subject: [PATCH 3/4] gh-63016: Add flags parameter on mmap.flush (#139553) Co-authored-by: Victor Stinner --- Doc/library/mmap.rst | 30 ++++++++- Lib/test/test_mmap.py | 9 +++ ...5-10-04-20-48-02.gh-issue-63016.EC9QN_.rst | 1 + Modules/clinic/mmapmodule.c.h | 67 ++++++++++++++++--- Modules/mmapmodule.c | 23 +++++-- 5 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-20-48-02.gh-issue-63016.EC9QN_.rst diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index 41b90f2c3b3111..28b2d1e244787a 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -212,7 +212,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length Writable :term:`bytes-like object` is now accepted. - .. method:: flush([offset[, size]]) + .. method:: flush([offset[, size]], *, flags=MS_SYNC) Flushes changes made to the in-memory copy of a file back to disk. Without use of this call there is no guarantee that changes are written back before @@ -221,6 +221,12 @@ To map anonymous memory, -1 should be passed as the fileno along with the length whole extent of the mapping is flushed. *offset* must be a multiple of the :const:`PAGESIZE` or :const:`ALLOCATIONGRANULARITY`. + The *flags* parameter specifies the synchronization behavior. + *flags* must be one of the :ref:`MS_* constants ` available + on the system. + + On Windows, the *flags* parameter is ignored. + ``None`` is returned to indicate success. An exception is raised when the call failed. @@ -235,6 +241,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length specified alone, and the flush operation will extend from *offset* to the end of the mmap. + .. versionchanged:: next + Added *flags* parameter to control synchronization behavior. + .. method:: madvise(option[, start[, length]]) @@ -461,3 +470,22 @@ MAP_* Constants :data:`MAP_TPRO`, :data:`MAP_TRANSLATED_ALLOW_EXECUTE`, and :data:`MAP_UNIX03` constants. +.. _ms-constants: + +MS_* Constants +++++++++++++++ + +.. data:: MS_SYNC + MS_ASYNC + MS_INVALIDATE + + These flags control the synchronization behavior for :meth:`mmap.flush`: + + * :data:`MS_SYNC` - Synchronous flush: writes are scheduled and the call + blocks until they are physically written to storage. + * :data:`MS_ASYNC` - Asynchronous flush: writes are scheduled but the call + returns immediately without waiting for completion. + * :data:`MS_INVALIDATE` - Invalidate cached data: invalidates other mappings + of the same file so they can see the changes. + + .. versionadded:: next diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index aad916ecfe2c27..bc3593ce4ba992 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1166,6 +1166,15 @@ def test_flush_parameters(self): m.flush(PAGESIZE) m.flush(PAGESIZE, PAGESIZE) + if hasattr(mmap, 'MS_SYNC'): + m.flush(0, PAGESIZE, flags=mmap.MS_SYNC) + if hasattr(mmap, 'MS_ASYNC'): + m.flush(flags=mmap.MS_ASYNC) + if hasattr(mmap, 'MS_INVALIDATE'): + m.flush(PAGESIZE * 2, flags=mmap.MS_INVALIDATE) + if hasattr(mmap, 'MS_ASYNC') and hasattr(mmap, 'MS_INVALIDATE'): + m.flush(0, PAGESIZE, flags=mmap.MS_ASYNC | mmap.MS_INVALIDATE) + @unittest.skipUnless(sys.platform == 'linux', 'Linux only') @support.requires_linux_version(5, 17, 0) def test_set_name(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-20-48-02.gh-issue-63016.EC9QN_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-20-48-02.gh-issue-63016.EC9QN_.rst new file mode 100644 index 00000000000000..a0aee6ce83a508 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-20-48-02.gh-issue-63016.EC9QN_.rst @@ -0,0 +1 @@ +Add a ``flags`` parameter to :meth:`mmap.mmap.flush` to control synchronization behavior. diff --git a/Modules/clinic/mmapmodule.c.h b/Modules/clinic/mmapmodule.c.h index b63f7df2a7e334..db640800ad780f 100644 --- a/Modules/clinic/mmapmodule.c.h +++ b/Modules/clinic/mmapmodule.c.h @@ -2,6 +2,10 @@ preserve [clinic start generated code]*/ +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif #include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() #include "pycore_modsupport.h" // _PyArg_CheckPositional() @@ -371,29 +375,63 @@ mmap_mmap_tell(PyObject *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(mmap_mmap_flush__doc__, -"flush($self, offset=0, size=-1, /)\n" +"flush($self, offset=0, size=-1, /, *, flags=0)\n" "--\n" "\n"); #define MMAP_MMAP_FLUSH_METHODDEF \ - {"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL, mmap_mmap_flush__doc__}, + {"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL|METH_KEYWORDS, mmap_mmap_flush__doc__}, static PyObject * -mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size); +mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size, + int flags); static PyObject * -mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "flush", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; Py_ssize_t offset = 0; Py_ssize_t size = -1; + int flags = 0; - if (!_PyArg_CheckPositional("flush", nargs, 0, 2)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } if (nargs < 1) { - goto skip_optional; + goto skip_optional_posonly; } + noptargs--; { Py_ssize_t ival = -1; PyObject *iobj = _PyNumber_Index(args[0]); @@ -407,8 +445,9 @@ mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs) offset = ival; } if (nargs < 2) { - goto skip_optional; + goto skip_optional_posonly; } + noptargs--; { Py_ssize_t ival = -1; PyObject *iobj = _PyNumber_Index(args[1]); @@ -421,9 +460,17 @@ mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } size = ival; } -skip_optional: +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_kwonly; + } + flags = PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_kwonly: Py_BEGIN_CRITICAL_SECTION(self); - return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size); + return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size, flags); Py_END_CRITICAL_SECTION(); exit: @@ -832,4 +879,4 @@ mmap_mmap_madvise(PyObject *self, PyObject *const *args, Py_ssize_t nargs) #ifndef MMAP_MMAP_MADVISE_METHODDEF #define MMAP_MMAP_MADVISE_METHODDEF #endif /* !defined(MMAP_MMAP_MADVISE_METHODDEF) */ -/*[clinic end generated code: output=fd9ca0ef425af934 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8389e3c8e3db3a78 input=a9049054013a1b77]*/ diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 0928ea6a8b70ba..16e3c0ecefd05d 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1034,12 +1034,15 @@ mmap.mmap.flush offset: Py_ssize_t = 0 size: Py_ssize_t = -1 / + * + flags: int = 0 [clinic start generated code]*/ static PyObject * -mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size) -/*[clinic end generated code: output=956ced67466149cf input=c50b893bc69520ec]*/ +mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size, + int flags) +/*[clinic end generated code: output=4225f4174dc75a53 input=42ba5fb716b6c294]*/ { CHECK_VALID(NULL); if (size == -1) { @@ -1060,8 +1063,10 @@ mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size) } Py_RETURN_NONE; #elif defined(UNIX) - /* XXX flags for msync? */ - if (-1 == msync(self->data + offset, size, MS_SYNC)) { + if (flags == 0) { + flags = MS_SYNC; + } + if (-1 == msync(self->data + offset, size, flags)) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -2331,6 +2336,16 @@ mmap_exec(PyObject *module) ADD_INT_MACRO(module, ACCESS_WRITE); ADD_INT_MACRO(module, ACCESS_COPY); +#ifdef MS_INVALIDATE + ADD_INT_MACRO(module, MS_INVALIDATE); +#endif +#ifdef MS_ASYNC + ADD_INT_MACRO(module, MS_ASYNC); +#endif +#ifdef MS_SYNC + ADD_INT_MACRO(module, MS_SYNC); +#endif + #ifdef HAVE_MADVISE // Conventional advice values #ifdef MADV_NORMAL From f5e11facf2d3d89ea8c387376d5889b959c60d82 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Sat, 27 Dec 2025 07:48:01 -0300 Subject: [PATCH 4/4] no-issue: Fix override value in os.rst (gh-123522) --- Doc/library/os.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 671270d6112212..f75ad4e67a66d7 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -5993,7 +5993,7 @@ Miscellaneous System Information .. versionchanged:: 3.13 If :option:`-X cpu_count <-X>` is given or :envvar:`PYTHON_CPU_COUNT` is set, - :func:`cpu_count` returns the overridden value *n*. + :func:`cpu_count` returns the override value *n*. .. function:: getloadavg() @@ -6015,7 +6015,7 @@ Miscellaneous System Information in the **system**. If :option:`-X cpu_count <-X>` is given or :envvar:`PYTHON_CPU_COUNT` is set, - :func:`process_cpu_count` returns the overridden value *n*. + :func:`process_cpu_count` returns the override value *n*. See also the :func:`sched_getaffinity` function.