[Python-checkins] gh-112532: Fix memory block count for free-threaded build (gh-113995)

2024-01-15 Thread corona10
https://github.com/python/cpython/commit/44e47dfba55a825ce7c340b1460cb493165353c9
commit: 44e47dfba55a825ce7c340b1460cb493165353c9
branch: main
author: Sam Gross 
committer: corona10 
date: 2024-01-16T00:37:36+09:00
summary:

gh-112532: Fix memory block count for free-threaded build (gh-113995)

This fixes `_PyInterpreterState_GetAllocatedBlocks()` and
`_Py_GetGlobalAllocatedBlocks()` in the free-threaded builds. The
gh-113263 change that introduced multiple mimalloc heaps per-thread
broke the logic for counting the number of allocated blocks. For subtle
reasons, this led to reported reference count leaks in the refleaks
buildbots.

files:
M Objects/obmalloc.c

diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 883adcb1c19b6e..88ad305ad776b0 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -626,12 +626,16 @@ _PyMem_PymallocEnabled(void)
 static int
 _PyMem_MimallocEnabled(void)
 {
+#ifdef Py_GIL_DISABLED
+return 1;
+#else
 if (_PyMem_DebugEnabled()) {
 return (_PyMem_Debug.obj.alloc.malloc == _PyObject_MiMalloc);
 }
 else {
 return (_PyObject.malloc == _PyObject_MiMalloc);
 }
+#endif
 }
 #endif  // WITH_MIMALLOC
 
@@ -1041,20 +1045,35 @@ static bool count_blocks(
 *(size_t *)allocated_blocks += area->used;
 return 1;
 }
+
+static Py_ssize_t
+get_mimalloc_allocated_blocks(PyInterpreterState *interp)
+{
+size_t allocated_blocks = 0;
+#ifdef Py_GIL_DISABLED
+for (PyThreadState *t = interp->threads.head; t != NULL; t = t->next) {
+_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)t;
+for (int i = 0; i < _Py_MIMALLOC_HEAP_COUNT; i++) {
+mi_heap_t *heap = &tstate->mimalloc.heaps[i];
+mi_heap_visit_blocks(heap, false, &count_blocks, 
&allocated_blocks);
+}
+}
+// TODO(sgross): count blocks in abandoned segments.
+#else
+// TODO(sgross): this only counts the current thread's blocks.
+mi_heap_t *heap = mi_heap_get_default();
+mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks);
+#endif
+return allocated_blocks;
+}
 #endif
 
 Py_ssize_t
 _PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *interp)
 {
 #ifdef WITH_MIMALLOC
-// TODO(sgross): this only counts the current thread's blocks.
 if (_PyMem_MimallocEnabled()) {
-size_t allocated_blocks = 0;
-
-mi_heap_t *heap = mi_heap_get_default();
-mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks);
-
-return allocated_blocks;
+return get_mimalloc_allocated_blocks(interp);
 }
 #endif
 
@@ -1105,7 +1124,7 @@ 
_PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *interp)
 
 static Py_ssize_t get_num_global_allocated_blocks(_PyRuntimeState *);
 
-/* We preserve the number of blockss leaked during runtime finalization,
+/* We preserve the number of blocks leaked during runtime finalization,
so they can be reported if the runtime is initialized again. */
 // XXX We don't lose any information by dropping this,
 // so we should consider doing so.
@@ -1121,16 +1140,6 @@ _Py_FinalizeAllocatedBlocks(_PyRuntimeState *runtime)
 static Py_ssize_t
 get_num_global_allocated_blocks(_PyRuntimeState *runtime)
 {
-#ifdef WITH_MIMALLOC
-if (_PyMem_MimallocEnabled()) {
-size_t allocated_blocks = 0;
-
-mi_heap_t *heap = mi_heap_get_default();
-mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks);
-
-return allocated_blocks;
-}
-#endif
 Py_ssize_t total = 0;
 if (_PyRuntimeState_GetFinalizing(runtime) != NULL) {
 PyInterpreterState *interp = _PyInterpreterState_Main();

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-111968: Use per-thread slice_cache in free-threading (gh-113972)

2024-01-15 Thread corona10
https://github.com/python/cpython/commit/3eae76554b0687c6b9c5c019cc53bb76430488c9
commit: 3eae76554b0687c6b9c5c019cc53bb76430488c9
branch: main
author: Donghee Na 
committer: corona10 
date: 2024-01-16T00:38:57+09:00
summary:

gh-111968: Use per-thread slice_cache in free-threading (gh-113972)

files:
M Include/internal/pycore_freelist.h
M Include/internal/pycore_gc.h
M Include/internal/pycore_interp.h
M Include/internal/pycore_sliceobject.h
M Objects/sliceobject.c
M Python/pylifecycle.c
M Python/pystate.c

diff --git a/Include/internal/pycore_freelist.h 
b/Include/internal/pycore_freelist.h
index 34009435910d99..faa0c11a49e798 100644
--- a/Include/internal/pycore_freelist.h
+++ b/Include/internal/pycore_freelist.h
@@ -59,10 +59,19 @@ struct _Py_float_state {
 #endif
 };
 
+struct _Py_slice_state {
+#ifdef WITH_FREELISTS
+/* Using a cache is very effective since typically only a single slice is
+   created and then deleted again. */
+PySliceObject *slice_cache;
+#endif
+};
+
 typedef struct _Py_freelist_state {
 struct _Py_float_state float_state;
 struct _Py_tuple_state tuple_state;
 struct _Py_list_state list_state;
+struct _Py_slice_state slice_state;
 } _PyFreeListState;
 
 #ifdef __cplusplus
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h
index c029b239306648..f8e86a22d0fa58 100644
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -249,6 +249,7 @@ extern void _Py_ClearFreeLists(_PyFreeListState *state, int 
is_finalization);
 extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int 
is_finalization);
 extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int 
is_finalization);
 extern void _PyList_ClearFreeList(_PyFreeListState *state, int 
is_finalization);
+extern void _PySlice_ClearCache(_PyFreeListState *state);
 extern void _PyDict_ClearFreeList(PyInterpreterState *interp);
 extern void _PyAsyncGen_ClearFreeLists(PyInterpreterState *interp);
 extern void _PyContext_ClearFreeList(PyInterpreterState *interp);
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index dadc8e3b91a75d..134a882695bbd7 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -187,9 +187,6 @@ struct _is {
 struct _Py_long_state long_state;
 struct _dtoa_state dtoa;
 struct _py_func_state func_state;
-/* Using a cache is very effective since typically only a single slice is
-   created and then deleted again. */
-PySliceObject *slice_cache;
 
 struct _Py_tuple_state tuple;
 struct _Py_dict_state dict_state;
diff --git a/Include/internal/pycore_sliceobject.h 
b/Include/internal/pycore_sliceobject.h
index 98665c3859d574..0c72d3ee6225c5 100644
--- a/Include/internal/pycore_sliceobject.h
+++ b/Include/internal/pycore_sliceobject.h
@@ -11,7 +11,7 @@ extern "C" {
 
 /* runtime lifecycle */
 
-extern void _PySlice_Fini(PyInterpreterState *);
+extern void _PySlice_Fini(_PyFreeListState *);
 
 extern PyObject *
 _PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop);
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index a3ed0c096d84ed..9ec8ea8e1b307f 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -103,16 +103,20 @@ PyObject _Py_EllipsisObject = 
_PyObject_HEAD_INIT(&PyEllipsis_Type);
 
 /* Slice object implementation */
 
-
-void _PySlice_Fini(PyInterpreterState *interp)
+void _PySlice_ClearCache(_PyFreeListState *state)
 {
-PySliceObject *obj = interp->slice_cache;
+PySliceObject *obj = state->slice_state.slice_cache;
 if (obj != NULL) {
-interp->slice_cache = NULL;
+state->slice_state.slice_cache = NULL;
 PyObject_GC_Del(obj);
 }
 }
 
+void _PySlice_Fini(_PyFreeListState *state)
+{
+_PySlice_ClearCache(state);
+}
+
 /* start, stop, and step are python objects with None indicating no
index is present.
 */
@@ -122,11 +126,11 @@ _PyBuildSlice_Consume2(PyObject *start, PyObject *stop, 
PyObject *step)
 {
 assert(start != NULL && stop != NULL && step != NULL);
 
-PyInterpreterState *interp = _PyInterpreterState_GET();
+_PyFreeListState *state = _PyFreeListState_GET();
 PySliceObject *obj;
-if (interp->slice_cache != NULL) {
-obj = interp->slice_cache;
-interp->slice_cache = NULL;
+if (state->slice_state.slice_cache != NULL) {
+obj = state->slice_state.slice_cache;
+state->slice_state.slice_cache = NULL;
 _Py_NewReference((PyObject *)obj);
 }
 else {
@@ -354,13 +358,13 @@ Create a slice object.  This is used for extended slicing 
(e.g. a[0:10:2]).");
 static void
 slice_dealloc(PySliceObject *r)
 {
-PyInterpreterState *interp = _PyInterpreterState_GET();
+_PyFreeListState *state = _PyFreeListState_GET();
 _PyObject_GC_UNTRACK(r);
 Py_DECREF(r->step);
 Py_DECREF(r->start);
 Py_DECREF(r->stop);
-if (interp->slice_cache == NULL) {
-interp->slice_cache = r;
+if (state->sl

[Python-checkins] gh-99437: runpy: decode path-like objects before setting globals

2024-01-15 Thread FFY00
https://github.com/python/cpython/commit/d457345bbc6414db0443819290b04a9a413d
commit: d457345bbc6414db0443819290b04a9a413d
branch: main
author: Kamil Turek 
committer: FFY00 
date: 2024-01-15T16:58:50Z
summary:

gh-99437: runpy: decode path-like objects before setting globals

files:
A Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst
M Lib/runpy.py
M Lib/test/test_runpy.py

diff --git a/Lib/runpy.py b/Lib/runpy.py
index 42f896c9cd5094..ef54d3282eee06 100644
--- a/Lib/runpy.py
+++ b/Lib/runpy.py
@@ -247,17 +247,17 @@ def _get_main_module_details(error=ImportError):
 sys.modules[main_name] = saved_main
 
 
-def _get_code_from_file(run_name, fname):
+def _get_code_from_file(fname):
 # Check for a compiled file first
 from pkgutil import read_code
-decoded_path = os.path.abspath(os.fsdecode(fname))
-with io.open_code(decoded_path) as f:
+code_path = os.path.abspath(fname)
+with io.open_code(code_path) as f:
 code = read_code(f)
 if code is None:
 # That didn't work, so try it as normal source code
-with io.open_code(decoded_path) as f:
+with io.open_code(code_path) as f:
 code = compile(f.read(), fname, 'exec')
-return code, fname
+return code
 
 def run_path(path_name, init_globals=None, run_name=None):
 """Execute code located at the specified filesystem location.
@@ -279,12 +279,13 @@ def run_path(path_name, init_globals=None, run_name=None):
 pkg_name = run_name.rpartition(".")[0]
 from pkgutil import get_importer
 importer = get_importer(path_name)
+path_name = os.fsdecode(path_name)
 if isinstance(importer, type(None)):
 # Not a valid sys.path entry, so run the code directly
 # execfile() doesn't help as we want to allow compiled files
-code, fname = _get_code_from_file(run_name, path_name)
+code = _get_code_from_file(path_name)
 return _run_module_code(code, init_globals, run_name,
-pkg_name=pkg_name, script_name=fname)
+pkg_name=pkg_name, script_name=path_name)
 else:
 # Finder is defined for path, so add it to
 # the start of sys.path
diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py
index 628c8cae38a751..57fe859e366b5b 100644
--- a/Lib/test/test_runpy.py
+++ b/Lib/test/test_runpy.py
@@ -661,8 +661,10 @@ def test_basic_script_with_path_object(self):
 mod_name = 'script'
 script_name = pathlib.Path(self._make_test_script(script_dir,
   mod_name))
-self._check_script(script_name, "", script_name,
-   script_name, expect_spec=False)
+self._check_script(script_name, "",
+   os.fsdecode(script_name),
+   os.fsdecode(script_name),
+   expect_spec=False)
 
 def test_basic_script_no_suffix(self):
 with temp_dir() as script_dir:
diff --git 
a/Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst 
b/Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst
new file mode 100644
index 00..da4e20f426b6cf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst
@@ -0,0 +1,2 @@
+:func:`runpy.run_path` now decodes path-like objects, making sure __file__
+and sys.argv[0] of the module being run are always strings.

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-114070: correct the specification of ``digit`` in the float() docs (#114080)

2024-01-15 Thread hauntsaninja
https://github.com/python/cpython/commit/4f24b92aa0677ed5310dd2d1572b55f4e30c88ef
commit: 4f24b92aa0677ed5310dd2d1572b55f4e30c88ef
branch: main
author: Sergey B Kirpichev 
committer: hauntsaninja <12621235+hauntsani...@users.noreply.github.com>
date: 2024-01-15T14:19:59-08:00
summary:

gh-114070: correct the specification of ``digit`` in the float() docs (#114080)

files:
M Doc/library/functions.rst

diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 4682ec9c924757..37234f7a5a2485 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -668,16 +668,15 @@ are always available.  They are listed here in 
alphabetical order.
   sign: "+" | "-"
   infinity: "Infinity" | "inf"
   nan: "nan"
-  digitpart: `!digit` (["_"] `!digit`)*
+  digit: 
+  digitpart: `digit` (["_"] `digit`)*
   number: [`digitpart`] "." `digitpart` | `digitpart` ["."]
   exponent: ("e" | "E") ["+" | "-"] `digitpart`
   floatnumber: number [`exponent`]
   floatvalue: [`sign`] (`floatnumber` | `infinity` | `nan`)
 
-   Here ``digit`` is a Unicode decimal digit (character in the Unicode general
-   category ``Nd``). Case is not significant, so, for example, "inf", "Inf",
-   "INFINITY", and "iNfINity" are all acceptable spellings for positive
-   infinity.
+   Case is not significant, so, for example, "inf", "Inf", "INFINITY", and
+   "iNfINity" are all acceptable spellings for positive infinity.
 
Otherwise, if the argument is an integer or a floating point number, a
floating point number with the same value (within Python's floating point

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.12] gh-114070: correct the specification of ``digit`` in the float() docs (GH-114080) (#114094)

2024-01-15 Thread hauntsaninja
https://github.com/python/cpython/commit/f6315edca13f7879aab8ec181289e6f40e2b36ea
commit: f6315edca13f7879aab8ec181289e6f40e2b36ea
branch: 3.12
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: hauntsaninja <12621235+hauntsani...@users.noreply.github.com>
date: 2024-01-15T22:25:51Z
summary:

[3.12] gh-114070: correct the specification of ``digit`` in the float() docs 
(GH-114080) (#114094)

gh-114070: correct the specification of ``digit`` in the float() docs 
(GH-114080)
(cherry picked from commit 4f24b92aa0677ed5310dd2d1572b55f4e30c88ef)

Co-authored-by: Sergey B Kirpichev 

files:
M Doc/library/functions.rst

diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 442cbdf1e6a7ca..b24680f9bc2a90 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -668,16 +668,15 @@ are always available.  They are listed here in 
alphabetical order.
   sign: "+" | "-"
   infinity: "Infinity" | "inf"
   nan: "nan"
-  digitpart: `!digit` (["_"] `!digit`)*
+  digit: 
+  digitpart: `digit` (["_"] `digit`)*
   number: [`digitpart`] "." `digitpart` | `digitpart` ["."]
   exponent: ("e" | "E") ["+" | "-"] `digitpart`
   floatnumber: number [`exponent`]
   floatvalue: [`sign`] (`floatnumber` | `infinity` | `nan`)
 
-   Here ``digit`` is a Unicode decimal digit (character in the Unicode general
-   category ``Nd``). Case is not significant, so, for example, "inf", "Inf",
-   "INFINITY", and "iNfINity" are all acceptable spellings for positive
-   infinity.
+   Case is not significant, so, for example, "inf", "Inf", "INFINITY", and
+   "iNfINity" are all acceptable spellings for positive infinity.
 
Otherwise, if the argument is an integer or a floating point number, a
floating point number with the same value (within Python's floating point

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.11] gh-114070: correct the specification of ``digit`` in the float() docs (GH-114080) (#114095)

2024-01-15 Thread hauntsaninja
https://github.com/python/cpython/commit/76433f8c45e978f48d642e070025b6e4e7207857
commit: 76433f8c45e978f48d642e070025b6e4e7207857
branch: 3.11
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: hauntsaninja <12621235+hauntsani...@users.noreply.github.com>
date: 2024-01-15T22:26:40Z
summary:

[3.11] gh-114070: correct the specification of ``digit`` in the float() docs 
(GH-114080) (#114095)

gh-114070: correct the specification of ``digit`` in the float() docs 
(GH-114080)
(cherry picked from commit 4f24b92aa0677ed5310dd2d1572b55f4e30c88ef)

Co-authored-by: Sergey B Kirpichev 

files:
M Doc/library/functions.rst

diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 22e46be9c200f8..a41a4d225baa61 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -667,16 +667,15 @@ are always available.  They are listed here in 
alphabetical order.
   sign: "+" | "-"
   infinity: "Infinity" | "inf"
   nan: "nan"
-  digitpart: `!digit` (["_"] `!digit`)*
+  digit: 
+  digitpart: `digit` (["_"] `digit`)*
   number: [`digitpart`] "." `digitpart` | `digitpart` ["."]
   exponent: ("e" | "E") ["+" | "-"] `digitpart`
   floatnumber: number [`exponent`]
   floatvalue: [`sign`] (`floatnumber` | `infinity` | `nan`)
 
-   Here ``digit`` is a Unicode decimal digit (character in the Unicode general
-   category ``Nd``). Case is not significant, so, for example, "inf", "Inf",
-   "INFINITY", and "iNfINity" are all acceptable spellings for positive
-   infinity.
+   Case is not significant, so, for example, "inf", "Inf", "INFINITY", and
+   "iNfINity" are all acceptable spellings for positive infinity.
 
Otherwise, if the argument is an integer or a floating point number, a
floating point number with the same value (within Python's floating point

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-91539: Small performance improvement of urrlib.request.getproxies_environment() (#108771)

2024-01-15 Thread hauntsaninja
https://github.com/python/cpython/commit/5094690efd7f663f2e0c1a2a633d3344a0557095
commit: 5094690efd7f663f2e0c1a2a633d3344a0557095
branch: main
author: Raphaƫl Marinier 
committer: hauntsaninja <12621235+hauntsani...@users.noreply.github.com>
date: 2024-01-15T15:45:01-08:00
summary:

gh-91539: Small performance improvement of 
urrlib.request.getproxies_environment() (#108771)

 Small performance improvement of getproxies_environment() when there are many 
environment variables. In a benchmark with 5k environment variables not related 
to proxies, and 5 specifying proxies, we get a 10% walltime improvement.

files:
A Misc/NEWS.d/next/Library/2023-09-01-15-33-18.gh-issue-91539.xoNLEI.rst
M Lib/urllib/request.py

diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index 1d03259b918c33..bca594420f6d9d 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -2490,7 +2490,7 @@ def getproxies_environment():
 # select only environment variables which end in (after making lowercase) 
_proxy
 proxies = {}
 environment = []
-for name in os.environ.keys():
+for name in os.environ:
 # fast screen underscore position before more expensive case-folding
 if len(name) > 5 and name[-6] == "_" and name[-5:].lower() == "proxy":
 value = os.environ[name]
diff --git 
a/Misc/NEWS.d/next/Library/2023-09-01-15-33-18.gh-issue-91539.xoNLEI.rst 
b/Misc/NEWS.d/next/Library/2023-09-01-15-33-18.gh-issue-91539.xoNLEI.rst
new file mode 100644
index 00..a1af479459d755
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-09-01-15-33-18.gh-issue-91539.xoNLEI.rst
@@ -0,0 +1 @@
+Small (10 - 20%) and trivial performance improvement of 
:func:`urrlib.request.getproxies_environment`, typically useful when there are 
many environment variables to go over.

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-112087: Update list impl to be thread-safe with manual CS (gh-113863)

2024-01-15 Thread corona10
https://github.com/python/cpython/commit/42b90cf0d6ca8aa78be3009b4f35de2e5c3155b8
commit: 42b90cf0d6ca8aa78be3009b4f35de2e5c3155b8
branch: main
author: Donghee Na 
committer: corona10 
date: 2024-01-16T09:11:14+09:00
summary:

gh-112087: Update list impl to be thread-safe with manual CS (gh-113863)

files:
M Objects/clinic/listobject.c.h
M Objects/listobject.c

diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h
index cf6f7449df5e1d..a61550a49b66fc 100644
--- a/Objects/clinic/listobject.c.h
+++ b/Objects/clinic/listobject.c.h
@@ -92,7 +92,13 @@ list_copy_impl(PyListObject *self);
 static PyObject *
 list_copy(PyListObject *self, PyObject *Py_UNUSED(ignored))
 {
-return list_copy_impl(self);
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = list_copy_impl(self);
+Py_END_CRITICAL_SECTION();
+
+return return_value;
 }
 
 PyDoc_STRVAR(list_append__doc__,
@@ -104,6 +110,21 @@ PyDoc_STRVAR(list_append__doc__,
 #define LIST_APPEND_METHODDEF\
 {"append", (PyCFunction)list_append, METH_O, list_append__doc__},
 
+static PyObject *
+list_append_impl(PyListObject *self, PyObject *object);
+
+static PyObject *
+list_append(PyListObject *self, PyObject *object)
+{
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = list_append_impl(self, object);
+Py_END_CRITICAL_SECTION();
+
+return return_value;
+}
+
 PyDoc_STRVAR(py_list_extend__doc__,
 "extend($self, iterable, /)\n"
 "--\n"
@@ -113,6 +134,21 @@ PyDoc_STRVAR(py_list_extend__doc__,
 #define PY_LIST_EXTEND_METHODDEF\
 {"extend", (PyCFunction)py_list_extend, METH_O, py_list_extend__doc__},
 
+static PyObject *
+py_list_extend_impl(PyListObject *self, PyObject *iterable);
+
+static PyObject *
+py_list_extend(PyListObject *self, PyObject *iterable)
+{
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION2(self, iterable);
+return_value = py_list_extend_impl(self, iterable);
+Py_END_CRITICAL_SECTION2();
+
+return return_value;
+}
+
 PyDoc_STRVAR(list_pop__doc__,
 "pop($self, index=-1, /)\n"
 "--\n"
@@ -416,4 +452,4 @@ list___reversed__(PyListObject *self, PyObject 
*Py_UNUSED(ignored))
 {
 return list___reversed___impl(self);
 }
-/*[clinic end generated code: output=3c9f24fd3212b18b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=26dfb2c9846348f9 input=a9049054013a1b77]*/
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 288c704be9842a..79ef8f532fbb98 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -263,15 +263,22 @@ PyList_SetItem(PyObject *op, Py_ssize_t i,
 PyErr_BadInternalCall();
 return -1;
 }
-if (!valid_index(i, Py_SIZE(op))) {
+int ret;
+PyListObject *self = ((PyListObject *)op);
+Py_BEGIN_CRITICAL_SECTION(self);
+if (!valid_index(i, Py_SIZE(self))) {
 Py_XDECREF(newitem);
 PyErr_SetString(PyExc_IndexError,
 "list assignment index out of range");
-return -1;
+ret = -1;
+goto end;
 }
-p = ((PyListObject *)op) -> ob_item + i;
+p = self->ob_item + i;
 Py_XSETREF(*p, newitem);
-return 0;
+ret = 0;
+end:
+Py_END_CRITICAL_SECTION();
+return ret;
 }
 
 static int
@@ -309,7 +316,12 @@ PyList_Insert(PyObject *op, Py_ssize_t where, PyObject 
*newitem)
 PyErr_BadInternalCall();
 return -1;
 }
-return ins1((PyListObject *)op, where, newitem);
+PyListObject *self = (PyListObject *)op;
+int err;
+Py_BEGIN_CRITICAL_SECTION(self);
+err = ins1(self, where, newitem);
+Py_END_CRITICAL_SECTION();
+return err;
 }
 
 /* internal, used by _PyList_AppendTakeRef */
@@ -804,9 +816,13 @@ static PyObject *
 list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object)
 /*[clinic end generated code: output=7f35e32f60c8cb78 input=b1987ca998a4ae2d]*/
 {
-if (ins1(self, index, object) == 0)
-Py_RETURN_NONE;
-return NULL;
+PyObject *ret = Py_None;
+Py_BEGIN_CRITICAL_SECTION(self);
+if (ins1(self, index, object) < 0) {
+ret = NULL;
+}
+Py_END_CRITICAL_SECTION();
+return ret;
 }
 
 /*[clinic input]
@@ -825,6 +841,7 @@ py_list_clear_impl(PyListObject *self)
 }
 
 /*[clinic input]
+@critical_section
 list.copy
 
 Return a shallow copy of the list.
@@ -832,12 +849,13 @@ Return a shallow copy of the list.
 
 static PyObject *
 list_copy_impl(PyListObject *self)
-/*[clinic end generated code: output=ec6b72d6209d418e input=6453ab159e84771f]*/
+/*[clinic end generated code: output=ec6b72d6209d418e input=81c54b0c7bb4f73d]*/
 {
 return list_slice(self, 0, Py_SIZE(self));
 }
 
 /*[clinic input]
+@critical_section
 list.append
 
  object: object
@@ -847,8 +865,8 @@ Append object to the end of the list.
 [clinic start generated code]*/
 
 static PyObject *
-list_append(PyListObject *self, PyObject *object)
-/*[clinic end generated code: output

[Python-checkins] [3.11] GH-101130: Document multiple arguments for `PurePath.[is_]relative_to()` (#114034)

2024-01-15 Thread barneygale
https://github.com/python/cpython/commit/f5cbed1114cae19744a9f9a460154322688b6318
commit: f5cbed1114cae19744a9f9a460154322688b6318
branch: 3.11
author: Barney Gale 
committer: barneygale 
date: 2024-01-16T01:37:55Z
summary:

[3.11] GH-101130: Document multiple arguments for `PurePath.[is_]relative_to()` 
(#114034)

3.11-only change as this is already covered in the 3.12+ deprecation
warning.

files:
M Doc/library/pathlib.rst

diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst
index 974ab424a57f54..2d35285c12bd31 100644
--- a/Doc/library/pathlib.rst
+++ b/Doc/library/pathlib.rst
@@ -508,6 +508,8 @@ Pure paths provide the following methods and properties:
   >>> p.is_relative_to('/usr')
   False
 
+   If multiple arguments are supplied, they are joined together.
+
.. versionadded:: 3.9
 
 
@@ -589,6 +591,8 @@ Pure paths provide the following methods and properties:
   .format(str(self), str(formatted)))
   ValueError: '/etc/passwd' is not in the subpath of '/usr' OR one path is 
relative and the other absolute.
 
+   If multiple arguments are supplied, they are joined together.
+
NOTE: This function is part of :class:`PurePath` and works with strings. It 
does not check or access the underlying file structure.
 
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.12] Update KDE recipe to match the standard use of the h parameter (gh-113958) (#114098)

2024-01-15 Thread rhettinger
https://github.com/python/cpython/commit/2b025793e122717d5b021f33079e632d54cf6052
commit: 2b025793e122717d5b021f33079e632d54cf6052
branch: 3.12
author: Raymond Hettinger 
committer: rhettinger 
date: 2024-01-15T22:46:01-06:00
summary:

[3.12] Update KDE recipe to match the standard use of the h parameter 
(gh-113958) (#114098)

files:
M Doc/library/statistics.rst

diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst
index 36f47b92ee3df5..3a4d265a6a8daf 100644
--- a/Doc/library/statistics.rst
+++ b/Doc/library/statistics.rst
@@ -1094,17 +1094,15 @@ from a fixed number of discrete samples.
 The basic idea is to smooth the data using `a kernel function such as a
 normal distribution, triangular distribution, or uniform distribution
 
`_.
-The degree of smoothing is controlled by a single
-parameter, ``h``, representing the variance of the kernel function.
+The degree of smoothing is controlled by a scaling parameter, ``h``,
+which is called the *bandwidth*.
 
 .. testcode::
 
-   import math
-
def kde_normal(sample, h):
"Create a continuous probability density function from a sample."
-   # Smooth the sample with a normal distribution of variance h.
-   kernel_h = NormalDist(0.0, math.sqrt(h)).pdf
+   # Smooth the sample with a normal distribution kernel scaled by h.
+   kernel_h = NormalDist(0.0, h).pdf
n = len(sample)
def pdf(x):
return sum(kernel_h(x - x_i) for x_i in sample) / n
@@ -1118,7 +1116,7 @@ a probability density function estimated from a small 
sample:
 .. doctest::
 
>>> sample = [-2.1, -1.3, -0.4, 1.9, 5.1, 6.2]
-   >>> f_hat = kde_normal(sample, h=2.25)
+   >>> f_hat = kde_normal(sample, h=1.5)
>>> xarr = [i/100 for i in range(-750, 1100)]
>>> yarr = [f_hat(x) for x in xarr]
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-78502: Add a trackfd parameter to mmap.mmap() (GH-25425)

2024-01-15 Thread encukou
https://github.com/python/cpython/commit/8fd287b18f20f0a310203f574adec196530627c7
commit: 8fd287b18f20f0a310203f574adec196530627c7
branch: main
author: Zackery Spytz 
committer: encukou 
date: 2024-01-16T08:51:46+01:00
summary:

gh-78502: Add a trackfd parameter to mmap.mmap() (GH-25425)

If *trackfd* is False, the file descriptor specified by *fileno*
will not be duplicated.

Co-authored-by: Erlend E. Aasland 
Co-authored-by: Petr Viktorin 
Co-authored-by: Serhiy Storchaka 

files:
A Misc/NEWS.d/next/Library/2021-04-15-10-41-51.bpo-34321.36m6_l.rst
M Doc/library/mmap.rst
M Doc/whatsnew/3.13.rst
M Lib/test/test_mmap.py
M Modules/mmapmodule.c

diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst
index ef6631ddcc68c8..758721433f77de 100644
--- a/Doc/library/mmap.rst
+++ b/Doc/library/mmap.rst
@@ -48,7 +48,7 @@ update the underlying file.
 
 To map anonymous memory, -1 should be passed as the fileno along with the 
length.
 
-.. class:: mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])
+.. class:: mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT, offset=0)
 
**(Windows version)** Maps *length* bytes from the file specified by the
file handle *fileno*, and creates a mmap object.  If *length* is larger
@@ -71,7 +71,8 @@ To map anonymous memory, -1 should be passed as the fileno 
along with the length
 
.. audit-event:: mmap.__new__ fileno,length,access,offset mmap.mmap
 
-.. class:: mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, 
access=ACCESS_DEFAULT[, offset])
+.. class:: mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, \
+access=ACCESS_DEFAULT, offset=0, *, trackfd=True)
:noindex:
 
**(Unix version)** Maps *length* bytes from the file specified by the file
@@ -102,10 +103,20 @@ To map anonymous memory, -1 should be passed as the 
fileno along with the length
defaults to 0. *offset* must be a multiple of :const:`ALLOCATIONGRANULARITY`
which is equal to :const:`PAGESIZE` on Unix systems.
 
+   If *trackfd* is ``False``, the file descriptor specified by *fileno* will
+   not be duplicated, and the resulting :class:`!mmap` object will not
+   be associated with the map's underlying file.
+   This means that the :meth:`~mmap.mmap.size` and :meth:`~mmap.mmap.resize`
+   methods will fail.
+   This mode is useful to limit the number of open file descriptors.
+
To ensure validity of the created memory mapping the file specified
by the descriptor *fileno* is internally automatically synchronized
with the physical backing store on macOS.
 
+   .. versionchanged:: 3.13
+  The *trackfd* parameter was added.
+
This example shows a simple way of using :class:`~mmap.mmap`::
 
   import mmap
@@ -254,9 +265,12 @@ To map anonymous memory, -1 should be passed as the fileno 
along with the length
 
.. method:: resize(newsize)
 
-  Resizes the map and the underlying file, if any. If the mmap was created
-  with :const:`ACCESS_READ` or :const:`ACCESS_COPY`, resizing the map will
-  raise a :exc:`TypeError` exception.
+  Resizes the map and the underlying file, if any.
+
+  Resizing a map created with *access* of :const:`ACCESS_READ` or
+  :const:`ACCESS_COPY`, will raise a :exc:`TypeError` exception.
+  Resizing a map created with with *trackfd* set to ``False``,
+  will raise a :exc:`ValueError` exception.
 
   **On Windows**: Resizing the map will raise an :exc:`OSError` if there 
are other
   maps against the same named file. Resizing an anonymous map (ie against 
the
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 05b9b87a63252f..e96fcf9f5b0385 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -254,6 +254,9 @@ mmap
   that can be used where it requires a file-like object with seekable and
   the :meth:`~mmap.mmap.seek` method return the new absolute position.
   (Contributed by Donghee Na and Sylvie Liberman in :gh:`111835`.)
+* :class:`mmap.mmap` now has a *trackfd* parameter on Unix; if it is ``False``,
+  the file descriptor specified by *fileno* will not be duplicated.
+  (Contributed by Zackery Spytz and Petr Viktorin in :gh:`78502`.)
 
 opcode
 --
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index f1e4b1efe2d0aa..b89621e08577be 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -4,6 +4,7 @@
 from test.support.import_helper import import_module
 from test.support.os_helper import TESTFN, unlink
 import unittest
+import errno
 import os
 import re
 import itertools
@@ -266,6 +267,62 @@ def test_access_parameter(self):
 self.assertRaises(TypeError, m.write_byte, 0)
 m.close()
 
+@unittest.skipIf(os.name == 'nt', 'trackfd not present on Windows')
+def test_trackfd_parameter(self):
+size = 64
+with open(TESTFN, "wb") as f:
+f.write(b"a"*size)
+for close_original_fd in True, False:
+with self

[Python-checkins] gh-114075: Capture `test_compileall` stdout output (#114076)

2024-01-15 Thread AlexWaygood
https://github.com/python/cpython/commit/892155d7365c9c4a6c2dd6850b4527222ba5c217
commit: 892155d7365c9c4a6c2dd6850b4527222ba5c217
branch: main
author: Kirill Podoprigora 
committer: AlexWaygood 
date: 2024-01-15T10:21:34Z
summary:

gh-114075: Capture `test_compileall` stdout output  (#114076)

Co-authored-by: Alex Waygood 

files:
M Lib/test/test_compileall.py

diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py
index 83a9532aecfac8..0ec6013dc11e3e 100644
--- a/Lib/test/test_compileall.py
+++ b/Lib/test/test_compileall.py
@@ -369,7 +369,9 @@ def test_strip_only_invalid(self):
 script = script_helper.make_script(path, "test", "1 / 0")
 bc = importlib.util.cache_from_source(script)
 stripdir = os.path.join(self.directory, *(fullpath[:2] + ['fake']))
-compileall.compile_dir(path, quiet=True, stripdir=stripdir)
+with support.captured_stdout() as out:
+compileall.compile_dir(path, quiet=True, stripdir=stripdir)
+self.assertIn("not a valid prefix", out.getvalue())
 rc, out, err = script_helper.assert_python_failure(bc)
 expected_not_in = os.path.join(self.directory, *fullpath[2:])
 self.assertIn(

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-113666: Adding missing UF_ and SF_ flags to module 'stat' (#113667)

2024-01-15 Thread ronaldoussoren
https://github.com/python/cpython/commit/2010d45327128594aed332befa687c8aead010bc
commit: 2010d45327128594aed332befa687c8aead010bc
branch: main
author: Ronald Oussoren 
committer: ronaldoussoren 
date: 2024-01-15T12:22:43+01:00
summary:

gh-113666: Adding missing UF_ and SF_ flags to module 'stat' (#113667)

Add some constants to module 'stat' that are used on macOS.

Co-authored-by: Serhiy Storchaka 

files:
A Misc/NEWS.d/next/macOS/2024-01-02-22-25-21.gh-issue-113666.xKZoBm.rst
M Doc/library/stat.rst
M Lib/stat.py
M Lib/test/test_stat.py
M Modules/_stat.c

diff --git a/Doc/library/stat.rst b/Doc/library/stat.rst
index 77538514598a50..c941d5557e31b5 100644
--- a/Doc/library/stat.rst
+++ b/Doc/library/stat.rst
@@ -350,6 +350,12 @@ The following flags can also be used in the *mode* 
argument of :func:`os.chmod`:
 
 The following flags can be used in the *flags* argument of :func:`os.chflags`:
 
+.. data:: UF_SETTABLE
+
+   All user settable flags.
+
+   .. versionadded: 3.13
+
 .. data:: UF_NODUMP
 
Do not dump the file.
@@ -374,10 +380,44 @@ The following flags can be used in the *flags* argument 
of :func:`os.chflags`:
 
The file is stored compressed (macOS 10.6+).
 
+.. data:: UF_TRACKED
+
+   Used for handling document IDs (macOS)
+
+   .. versionadded: 3.13
+
+.. data:: UF_DATAVAULT
+
+   The file needs an entitlement for reading or writing (macOS 10.13+)
+
+   .. versionadded: 3.13
+
 .. data:: UF_HIDDEN
 
The file should not be displayed in a GUI (macOS 10.5+).
 
+.. data:: SF_SETTABLE
+
+   All super-user changeable flags
+
+   .. versionadded: 3.13
+
+.. data:: SF_SUPPORTED
+
+   All super-user supported flags
+
+   .. availability:: macOS
+
+   .. versionadded: 3.13
+
+.. data:: SF_SYNTHETIC
+
+   All super-user read-only synthetic flags
+
+   .. availability:: macOS
+
+   .. versionadded: 3.13
+
 .. data:: SF_ARCHIVED
 
The file may be archived.
@@ -390,6 +430,12 @@ The following flags can be used in the *flags* argument of 
:func:`os.chflags`:
 
The file may only be appended to.
 
+.. data:: SF_RESTRICTED
+
+   The file needs an entitlement to write to (macOS 10.13+)
+
+   .. versionadded: 3.13
+
 .. data:: SF_NOUNLINK
 
The file may not be renamed or deleted.
@@ -398,6 +444,18 @@ The following flags can be used in the *flags* argument of 
:func:`os.chflags`:
 
The file is a snapshot file.
 
+.. data:: SF_FIRMLINK
+
+   The file is a firmlink (macOS 10.15+)
+
+   .. versionadded: 3.13
+
+.. data:: SF_DATALESS
+
+   The file is a dataless object (macOS 10.15+)
+
+   .. versionadded: 3.13
+
 See the \*BSD or macOS systems man page :manpage:`chflags(2)` for more 
information.
 
 On Windows, the following file attribute constants are available for use when
diff --git a/Lib/stat.py b/Lib/stat.py
index 52cadbf04f6c88..9167ab185944fb 100644
--- a/Lib/stat.py
+++ b/Lib/stat.py
@@ -2,6 +2,7 @@
 
 Suggested usage: from stat import *
 """
+import sys
 
 # Indices for stat struct members in the tuple returned by os.stat()
 
@@ -110,19 +111,25 @@ def S_ISWHT(mode):
 S_IXOTH = 0o0001  # execute by others
 
 # Names for file flags
-
+UF_SETTABLE  = 0x  # owner settable flags
 UF_NODUMP= 0x0001  # do not dump file
 UF_IMMUTABLE = 0x0002  # file may not be changed
 UF_APPEND= 0x0004  # file may only be appended to
 UF_OPAQUE= 0x0008  # directory is opaque when viewed through a union 
stack
 UF_NOUNLINK  = 0x0010  # file may not be renamed or deleted
-UF_COMPRESSED = 0x0020 # OS X: file is hfs-compressed
-UF_HIDDEN= 0x8000  # OS X: file should not be displayed
+UF_COMPRESSED = 0x0020 # macOS: file is compressed
+UF_TRACKED   = 0x0040  # macOS: used for handling document IDs
+UF_DATAVAULT = 0x0080  # macOS: entitlement needed for I/O
+UF_HIDDEN= 0x8000  # macOS: file should not be displayed
+SF_SETTABLE  = 0x  # superuser settable flags
 SF_ARCHIVED  = 0x0001  # file may be archived
 SF_IMMUTABLE = 0x0002  # file may not be changed
 SF_APPEND= 0x0004  # file may only be appended to
+SF_RESTRICTED = 0x0008 # macOS: entitlement needed for writing
 SF_NOUNLINK  = 0x0010  # file may not be renamed or deleted
 SF_SNAPSHOT  = 0x0020  # file is a snapshot file
+SF_FIRMLINK  = 0x0080  # macOS: file is a firmlink
+SF_DATALESS  = 0x4000  # macOS: file is a dataless object
 
 
 _filemode_table = (
diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py
index a0d0f61e5a192c..d6b6dd6e741700 100644
--- a/Lib/test/test_stat.py
+++ b/Lib/test/test_stat.py
@@ -15,8 +15,10 @@ class TestFilemode:
 statmod = None
 
 file_flags = {'SF_APPEND', 'SF_ARCHIVED', 'SF_IMMUTABLE', 'SF_NOUNLINK',
-  'SF_SNAPSHOT', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN',
-  'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE'}
+  'SF_SNAPSHOT', 'SF_SETTABLE', 'SF_RESTRICTED', 'SF_FIRMLINK',
+  'SF_DATALESS', 'UF_APPEND', 'UF_COMPRESSED', '

[Python-checkins] GH-112354: `_GUARD_IS_TRUE_POP` side-exits to target the next instruction, not themselves. (GH-114078)

2024-01-15 Thread markshannon
https://github.com/python/cpython/commit/ac10947ba79a15bfdaa3ca92c6864214648ab364
commit: ac10947ba79a15bfdaa3ca92c6864214648ab364
branch: main
author: Mark Shannon 
committer: markshannon 
date: 2024-01-15T11:41:06Z
summary:

GH-112354: `_GUARD_IS_TRUE_POP` side-exits to target the next instruction, not 
themselves. (GH-114078)

files:
M Include/internal/pycore_uop_metadata.h
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/optimizer.c
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/interpreter_definition.md
M Tools/cases_generator/stack.py

diff --git a/Include/internal/pycore_uop_metadata.h 
b/Include/internal/pycore_uop_metadata.h
index 3b251d3814b1da..9bfb4f4f3a4dea 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -169,7 +169,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
 [_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_PASSTHROUGH_FLAG,
 [_CHECK_STACK_SPACE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_PASSTHROUGH_FLAG,
 [_INIT_CALL_PY_EXACT_ARGS] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG | 
HAS_PURE_FLAG,
-[_PUSH_FRAME] = 0,
+[_PUSH_FRAME] = HAS_ESCAPES_FLAG,
 [_CALL_TYPE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
 [_CALL_STR_1] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
 [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 6df99d6465347f..c48f0a17c60fb1 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -805,7 +805,8 @@ dummy_func(
 #if TIER_ONE
 assert(frame != &entry_frame);
 #endif
-STORE_SP();
+SYNC_SP();
+_PyFrame_SetStackPointer(frame, stack_pointer);
 assert(EMPTY());
 _Py_LeaveRecursiveCallPy(tstate);
 // GH-99729: We need to unlink the frame *before* clearing it:
@@ -3154,7 +3155,8 @@ dummy_func(
 // Write it out explicitly because it's subtly different.
 // Eventually this should be the only occurrence of this code.
 assert(tstate->interp->eval_frame == NULL);
-STORE_SP();
+SYNC_SP();
+_PyFrame_SetStackPointer(frame, stack_pointer);
 new_frame->previous = frame;
 CALL_STAT_INC(inlined_py_calls);
 frame = tstate->current_frame = new_frame;
@@ -4013,20 +4015,27 @@ dummy_func(
 / Tier-2 only opcodes /
 
 op (_GUARD_IS_TRUE_POP, (flag -- )) {
-DEOPT_IF(Py_IsFalse(flag));
+SYNC_SP();
+DEOPT_IF(!Py_IsTrue(flag));
 assert(Py_IsTrue(flag));
 }
 
 op (_GUARD_IS_FALSE_POP, (flag -- )) {
-DEOPT_IF(Py_IsTrue(flag));
+SYNC_SP();
+DEOPT_IF(!Py_IsFalse(flag));
 assert(Py_IsFalse(flag));
 }
 
 op (_GUARD_IS_NONE_POP, (val -- )) {
-DEOPT_IF(!Py_IsNone(val));
+SYNC_SP();
+if (!Py_IsNone(val)) {
+Py_DECREF(val);
+DEOPT_IF(1);
+}
 }
 
 op (_GUARD_IS_NOT_NONE_POP, (val -- )) {
+SYNC_SP();
 DEOPT_IF(Py_IsNone(val));
 Py_DECREF(val);
 }
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 6060bebca9afa5..2b4399b25bae2b 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -3318,35 +3318,38 @@
 case _GUARD_IS_TRUE_POP: {
 PyObject *flag;
 flag = stack_pointer[-1];
-if (Py_IsFalse(flag)) goto deoptimize;
-assert(Py_IsTrue(flag));
 stack_pointer += -1;
+if (!Py_IsTrue(flag)) goto deoptimize;
+assert(Py_IsTrue(flag));
 break;
 }
 
 case _GUARD_IS_FALSE_POP: {
 PyObject *flag;
 flag = stack_pointer[-1];
-if (Py_IsTrue(flag)) goto deoptimize;
-assert(Py_IsFalse(flag));
 stack_pointer += -1;
+if (!Py_IsFalse(flag)) goto deoptimize;
+assert(Py_IsFalse(flag));
 break;
 }
 
 case _GUARD_IS_NONE_POP: {
 PyObject *val;
 val = stack_pointer[-1];
-if (!Py_IsNone(val)) goto deoptimize;
 stack_pointer += -1;
+if (!Py_IsNone(val)) {
+Py_DECREF(val);
+if (1) goto deoptimize;
+}
 break;
 }
 
 case _GUARD_IS_NOT_NONE_POP: {
 PyObject *val;
 val = stack_pointer[-1];
+stack_pointer += -1;
 if (Py_IsNone(val)) goto deoptimize;
 Py_DECREF(val);
-stack_pointer += -1;
 break;
 }
 
diff --git a/Python/optimizer.c b/Python/optim

[Python-checkins] gh-109598: make PyComplex_RealAsDouble/ImagAsDouble use __complex__ (GH-109647)

2024-01-15 Thread encukou
https://github.com/python/cpython/commit/0f2fa6150baf111a6c69d5d491c95c3c2ee60eaf
commit: 0f2fa6150baf111a6c69d5d491c95c3c2ee60eaf
branch: main
author: Sergey B Kirpichev 
committer: encukou 
date: 2024-01-15T16:04:17+01:00
summary:

gh-109598: make PyComplex_RealAsDouble/ImagAsDouble use __complex__ (GH-109647)

`PyComplex_RealAsDouble()`/`PyComplex_ImagAsDouble` now try to convert
an object to a `complex` instance using its `__complex__()` method
before falling back to the ``__float__()`` method.

PyComplex_ImagAsDouble() also will not silently return 0.0 for
non-complex types anymore.  Instead we try to call PyFloat_AsDouble()
and return 0.0 only if this call is successful.

files:
A Misc/NEWS.d/next/Core and 
Builtins/2023-09-21-11-54-28.gh-issue-109598.CRidSy.rst
M Doc/c-api/complex.rst
M Lib/test/test_capi/test_complex.py
M Objects/complexobject.c

diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst
index e3fd001c599c80..5a0474869071d9 100644
--- a/Doc/c-api/complex.rst
+++ b/Doc/c-api/complex.rst
@@ -117,11 +117,29 @@ Complex Numbers as Python Objects
 
Return the real part of *op* as a C :c:expr:`double`.
 
+   If *op* is not a Python complex number object but has a
+   :meth:`~object.__complex__` method, this method will first be called to
+   convert *op* to a Python complex number object.  If :meth:`!__complex__` is
+   not defined then it falls back to call :c:func:`PyFloat_AsDouble` and
+   returns its result.  Upon failure, this method returns ``-1.0``, so one
+   should call :c:func:`PyErr_Occurred` to check for errors.
+
+   .. versionchanged:: 3.13
+  Use :meth:`~object.__complex__` if available.
 
 .. c:function:: double PyComplex_ImagAsDouble(PyObject *op)
 
Return the imaginary part of *op* as a C :c:expr:`double`.
 
+   If *op* is not a Python complex number object but has a
+   :meth:`~object.__complex__` method, this method will first be called to
+   convert *op* to a Python complex number object.  If :meth:`!__complex__` is
+   not defined then it falls back to call :c:func:`PyFloat_AsDouble` and
+   returns ``0.0`` on success.  Upon failure, this method returns ``-1.0``, so
+   one should call :c:func:`PyErr_Occurred` to check for errors.
+
+   .. versionchanged:: 3.13
+  Use :meth:`~object.__complex__` if available.
 
 .. c:function:: Py_complex PyComplex_AsCComplex(PyObject *op)
 
diff --git a/Lib/test/test_capi/test_complex.py 
b/Lib/test/test_capi/test_complex.py
index d6fc1f077c40aa..a5b59558e7f851 100644
--- a/Lib/test/test_capi/test_complex.py
+++ b/Lib/test/test_capi/test_complex.py
@@ -77,8 +77,14 @@ def test_realasdouble(self):
 self.assertEqual(realasdouble(FloatSubclass(4.25)), 4.25)
 
 # Test types with __complex__ dunder method
-# Function doesn't support classes with __complex__ dunder, see #109598
-self.assertRaises(TypeError, realasdouble, Complex())
+self.assertEqual(realasdouble(Complex()), 4.25)
+self.assertRaises(TypeError, realasdouble, BadComplex())
+with self.assertWarns(DeprecationWarning):
+self.assertEqual(realasdouble(BadComplex2()), 4.25)
+with warnings.catch_warnings():
+warnings.simplefilter("error", DeprecationWarning)
+self.assertRaises(DeprecationWarning, realasdouble, BadComplex2())
+self.assertRaises(RuntimeError, realasdouble, BadComplex3())
 
 # Test types with __float__ dunder method
 self.assertEqual(realasdouble(Float()), 4.25)
@@ -104,11 +110,22 @@ def test_imagasdouble(self):
 self.assertEqual(imagasdouble(FloatSubclass(4.25)), 0.0)
 
 # Test types with __complex__ dunder method
-# Function doesn't support classes with __complex__ dunder, see #109598
-self.assertEqual(imagasdouble(Complex()), 0.0)
+self.assertEqual(imagasdouble(Complex()), 0.5)
+self.assertRaises(TypeError, imagasdouble, BadComplex())
+with self.assertWarns(DeprecationWarning):
+self.assertEqual(imagasdouble(BadComplex2()), 0.5)
+with warnings.catch_warnings():
+warnings.simplefilter("error", DeprecationWarning)
+self.assertRaises(DeprecationWarning, imagasdouble, BadComplex2())
+self.assertRaises(RuntimeError, imagasdouble, BadComplex3())
+
+# Test types with __float__ dunder method
+self.assertEqual(imagasdouble(Float()), 0.0)
+self.assertRaises(TypeError, imagasdouble, BadFloat())
+with self.assertWarns(DeprecationWarning):
+self.assertEqual(imagasdouble(BadFloat2()), 0.0)
 
-# Function returns 0.0 anyway, see #109598
-self.assertEqual(imagasdouble(object()), 0.0)
+self.assertRaises(TypeError, imagasdouble, object())
 
 # CRASHES imagasdouble(NULL)
 
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2023-09-21-11-54-28.gh-issue-109598.CRidSy.rst b/Misc/NEWS.d/next/Core 
and Builtins/2023-09-21-11-54-28.gh-issue-109598.CRidSy.rst
new file mode 10