[Python-checkins] gh-111178: fix UBSan failures in `Objects/typeobject.c` (#129799)
https://github.com/python/cpython/commit/3d40317ed24d03e9511ee96316bd204a8f041746 commit: 3d40317ed24d03e9511ee96316bd204a8f041746 branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-02-25T10:44:59Z summary: gh-78: fix UBSan failures in `Objects/typeobject.c` (#129799) Fix UBSan failures for `PyTypeObject`. Introduce a macro cast for `superobject` and remove redundant casts. Rename the unused parameter in getter/setter methods to `closure` for semantic purposes. files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1fa1220aeec648..458d78e0502723 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -84,6 +84,7 @@ class object "PyObject *" "&PyBaseObject_Type" #endif +#define PyTypeObject_CAST(op) ((PyTypeObject *)(op)) typedef struct PySlot_Offset { short subslot_offset; @@ -1334,11 +1335,11 @@ _PyType_Name(PyTypeObject *type) } static PyObject * -type_name(PyTypeObject *type, void *context) +type_name(PyObject *tp, void *Py_UNUSED(closure)) { +PyTypeObject *type = PyTypeObject_CAST(tp); if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { PyHeapTypeObject* et = (PyHeapTypeObject*)type; - return Py_NewRef(et->ht_name); } else { @@ -1347,8 +1348,9 @@ type_name(PyTypeObject *type, void *context) } static PyObject * -type_qualname(PyTypeObject *type, void *context) +type_qualname(PyObject *tp, void *Py_UNUSED(closure)) { +PyTypeObject *type = PyTypeObject_CAST(tp); if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { PyHeapTypeObject* et = (PyHeapTypeObject*)type; return Py_NewRef(et->ht_qualname); @@ -1359,8 +1361,9 @@ type_qualname(PyTypeObject *type, void *context) } static int -type_set_name(PyTypeObject *type, PyObject *value, void *context) +type_set_name(PyObject *tp, PyObject *value, void *Py_UNUSED(closure)) { +PyTypeObject *type = PyTypeObject_CAST(tp); const char *tp_name; Py_ssize_t name_size; @@ -1389,8 +1392,9 @@ type_set_name(PyTypeObject *type, PyObject *value, void *context) } static int -type_set_qualname(PyTypeObject *type, PyObject *value, void *context) +type_set_qualname(PyObject *tp, PyObject *value, void *context) { +PyTypeObject *type = PyTypeObject_CAST(tp); PyHeapTypeObject* et; if (!check_set_special_type_attr(type, value, "__qualname__")) @@ -1434,15 +1438,17 @@ type_module(PyTypeObject *type) return mod; } -static PyObject * -type_get_module(PyTypeObject *type, void *context) +static inline PyObject * +type_get_module(PyObject *tp, void *Py_UNUSED(closure)) { +PyTypeObject *type = PyTypeObject_CAST(tp); return type_module(type); } static int -type_set_module(PyTypeObject *type, PyObject *value, void *context) +type_set_module(PyObject *tp, PyObject *value, void *Py_UNUSED(closure)) { +PyTypeObject *type = PyTypeObject_CAST(tp); if (!check_set_special_type_attr(type, value, "__module__")) return -1; @@ -1463,7 +1469,7 @@ _PyType_GetFullyQualifiedName(PyTypeObject *type, char sep) return PyUnicode_FromString(type->tp_name); } -PyObject *qualname = type_qualname(type, NULL); +PyObject *qualname = type_qualname((PyObject *)type, NULL); if (qualname == NULL) { return NULL; } @@ -1495,11 +1501,11 @@ PyType_GetFullyQualifiedName(PyTypeObject *type) return _PyType_GetFullyQualifiedName(type, '.'); } - static PyObject * -type_abstractmethods(PyTypeObject *type, void *context) +type_abstractmethods(PyObject *tp, void *Py_UNUSED(closure)) { -PyObject *mod = NULL; +PyTypeObject *type = PyTypeObject_CAST(tp); +PyObject *res = NULL; /* type itself has an __abstractmethods__ descriptor (this). Don't return that. */ if (type == &PyType_Type) { @@ -1507,16 +1513,17 @@ type_abstractmethods(PyTypeObject *type, void *context) } else { PyObject *dict = lookup_tp_dict(type); -if (PyDict_GetItemRef(dict, &_Py_ID(__abstractmethods__), &mod) == 0) { +if (PyDict_GetItemRef(dict, &_Py_ID(__abstractmethods__), &res) == 0) { PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); } } -return mod; +return res; } static int -type_set_abstractmethods(PyTypeObject *type, PyObject *value, void *context) +type_set_abstractmethods(PyObject *tp, PyObject *value, void *Py_UNUSED(closure)) { +PyTypeObject *type = PyTypeObject_CAST(tp); /* __abstractmethods__ should only be set once on a type, in abc.ABCMeta.__new__, so this function doesn't do anything special to update subclasses. @@ -1550,8 +1557,9 @@ type_set_abstractmethods(PyTypeObject *type, PyObject *value, void *context) } static PyObject * -type_get_bases(PyTypeObject *type, void *context) +type_get_bases(PyObject *tp, void *Py_UNUSED(closure)) { +
[Python-checkins] [3.12] Fix a typo in code module test (GH-130530) (GH-130533)
https://github.com/python/cpython/commit/def2ee1280fa1efcf75fdff6db6ce07530f4cc10 commit: def2ee1280fa1efcf75fdff6db6ce07530f4cc10 branch: 3.12 author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com> committer: serhiy-storchaka date: 2025-02-25T09:54:15Z summary: [3.12] Fix a typo in code module test (GH-130530) (GH-130533) (cherry picked from commit 56e337d32b88630f2c35458231cd61929f1be6d4) Co-authored-by: Tian Gao files: M Lib/test/test_code_module.py diff --git a/Lib/test/test_code_module.py b/Lib/test/test_code_module.py index 06a1ba494be131..a79dd73a5b65de 100644 --- a/Lib/test/test_code_module.py +++ b/Lib/test/test_code_module.py @@ -46,9 +46,9 @@ def test_ps2(self): self.infunc.side_effect = EOFError('Finished') self.console.interact() self.assertEqual(self.sysmod.ps2, '... ') -self.sysmod.ps1 = 'custom2> ' +self.sysmod.ps2 = 'custom2> ' self.console.interact() -self.assertEqual(self.sysmod.ps1, 'custom2> ') +self.assertEqual(self.sysmod.ps2, 'custom2> ') def test_console_stderr(self): self.infunc.side_effect = ["'antioch'", "", EOFError('Finished')] ___ 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] Fix a typo in `Py_DECREF` comment (#128387)
https://github.com/python/cpython/commit/31ef8fd8e21141576796ef473c1fb7b4bffc5f0a commit: 31ef8fd8e21141576796ef473c1fb7b4bffc5f0a branch: main author: Justine Krejcha committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-02-25T11:10:40+01:00 summary: Fix a typo in `Py_DECREF` comment (#128387) files: M Include/refcount.h diff --git a/Include/refcount.h b/Include/refcount.h index d98b2dfcf37202..dbc69ee02b017d 100644 --- a/Include/refcount.h +++ b/Include/refcount.h @@ -313,7 +313,7 @@ PyAPI_FUNC(void) _Py_MergeZeroLocalRefcount(PyObject *); // Stable ABI implements Py_DECREF() as a function call on limited C API // version 3.12 and newer, and on Python built in debug mode. _Py_DecRef() was // added to Python 3.10.0a7, use Py_DecRef() on older Python versions. -// Py_DecRef() accepts NULL whereas _Py_IncRef() doesn't. +// Py_DecRef() accepts NULL whereas _Py_DecRef() doesn't. static inline void Py_DECREF(PyObject *op) { # if Py_LIMITED_API+0 >= 0x030a00A7 _Py_DecRef(op); ___ 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-130453: pygettext: Extend support for specifying custom keywords (GH-130463)
https://github.com/python/cpython/commit/44213bc57c0a4b674463e170ad9d80896d866a64 commit: 44213bc57c0a4b674463e170ad9d80896d866a64 branch: main author: Tomas R. committer: serhiy-storchaka date: 2025-02-25T12:10:54+02:00 summary: gh-130453: pygettext: Extend support for specifying custom keywords (GH-130463) files: A Lib/test/test_tools/i18n_data/custom_keywords.pot A Lib/test/test_tools/i18n_data/custom_keywords.py A Misc/NEWS.d/next/Tools-Demos/2025-02-22-18-08-35.gh-issue-130453.njRXG8.rst M Lib/test/test_tools/test_i18n.py M Tools/i18n/pygettext.py diff --git a/Lib/test/test_tools/i18n_data/custom_keywords.pot b/Lib/test/test_tools/i18n_data/custom_keywords.pot new file mode 100644 index 00..48df2e7f579cc7 --- /dev/null +++ b/Lib/test/test_tools/i18n_data/custom_keywords.pot @@ -0,0 +1,45 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2000-01-01 00:00+\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + + +#: custom_keywords.py:9 custom_keywords.py:10 +msgid "bar" +msgstr "" + +#: custom_keywords.py:12 +msgid "cat" +msgid_plural "cats" +msgstr[0] "" +msgstr[1] "" + +#: custom_keywords.py:13 +msgid "dog" +msgid_plural "dogs" +msgstr[0] "" +msgstr[1] "" + +#: custom_keywords.py:15 +msgctxt "context" +msgid "bar" +msgstr "" + +#: custom_keywords.py:17 +msgctxt "context" +msgid "cat" +msgid_plural "cats" +msgstr[0] "" +msgstr[1] "" + diff --git a/Lib/test/test_tools/i18n_data/custom_keywords.py b/Lib/test/test_tools/i18n_data/custom_keywords.py new file mode 100644 index 00..01ea56c348cb55 --- /dev/null +++ b/Lib/test/test_tools/i18n_data/custom_keywords.py @@ -0,0 +1,30 @@ +from gettext import ( +gettext as foo, +ngettext as nfoo, +pgettext as pfoo, +npgettext as npfoo, +gettext as bar, +) + +foo('bar') +foo('bar', 'baz') + +nfoo('cat', 'cats', 1) +nfoo('dog', 'dogs') + +pfoo('context', 'bar') + +npfoo('context', 'cat', 'cats', 1) + +# This is an unknown keyword and should be ignored +bar('baz') + +# 'nfoo' requires at least 2 arguments +nfoo('dog') + +# 'pfoo' requires at least 2 arguments +pfoo('context') + +# 'npfoo' requires at least 3 arguments +npfoo('context') +npfoo('context', 'cat') diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index d97fdb116fcd19..d73fcff4c9cb11 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -8,7 +8,7 @@ from pathlib import Path from test.support.script_helper import assert_python_ok -from test.test_tools import skip_if_missing, toolsdir +from test.test_tools import imports_under_tool, skip_if_missing, toolsdir from test.support.os_helper import temp_cwd, temp_dir @@ -17,6 +17,10 @@ DATA_DIR = Path(__file__).resolve().parent / 'i18n_data' +with imports_under_tool("i18n"): +from pygettext import parse_spec + + def normalize_POT_file(pot): """Normalize the POT creation timestamp, charset and file locations to make the POT file easier to compare. @@ -377,16 +381,8 @@ class _(object): def test_pygettext_output(self): """Test that the pygettext output exactly matches snapshots.""" -for input_file in DATA_DIR.glob('*.py'): -output_file = input_file.with_suffix('.pot') -with self.subTest(input_file=f'i18n_data/{input_file}'): -contents = input_file.read_text(encoding='utf-8') -with temp_cwd(None): -Path(input_file.name).write_text(contents) -assert_python_ok('-Xutf8', self.script, '--docstrings', - '--add-comments=i18n:', input_file.name) -output = Path('messages.pot').read_text(encoding='utf-8') - +for input_file, output_file, output in extract_from_snapshots(): +with self.subTest(input_file=input_file): expected = output_file.read_text(encoding='utf-8') self.assert_POT_equal(expected, output) @@ -485,17 +481,67 @@ def test_comments_not_extracted_without_tags(self): '''), raw=True) self.assertNotIn('#.', data) - -def update_POT_snapshots(): -for input_file in DATA_DIR.glob('*.py'): +def test_parse_keyword_spec(self): +valid = ( +('foo', ('foo', {0: 'msgid'})), +('foo:1', ('foo', {0: 'msgid'})), +('foo:1,2', ('foo', {0: 'msgid', 1: 'msgid_plural'})), +('foo:1, 2', ('foo', {0: 'msgid', 1: 'msgid_plural'})), +('foo:1,2c', ('foo', {0: 'msgid', 1: 'msgctxt'})), +('foo:2c,1', ('foo', {0: 'msgid', 1: 'msgctxt'})), +('foo:2c ,1', ('foo', {0: 'msgid', 1: 'msgctxt'}))
[Python-checkins] [3.12] gh-108303: Fix and move `badsyntax_pep3120.py` (GH-109513) (#130540)
https://github.com/python/cpython/commit/e28097682eb96550e30a66c65d929b412bf51d52 commit: e28097682eb96550e30a66c65d929b412bf51d52 branch: 3.12 author: Hugo van Kemenade <1324225+hug...@users.noreply.github.com> committer: hugovk <1324225+hug...@users.noreply.github.com> date: 2025-02-26T09:46:12+02:00 summary: [3.12] gh-108303: Fix and move `badsyntax_pep3120.py` (GH-109513) (#130540) (cherry picked from commit 4dd47c63a97b3c39cd964ad12431fcdaf76dc823) Co-authored-by: Nikita Sobolev Co-authored-by: Alex Waygood files: A Lib/test/tokenizedata/badsyntax_pep3120.py D Lib/test/badsyntax_pep3120.py M Lib/test/.ruff.toml M Lib/test/test_utf8source.py diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml index 1632900057cd74..79ee34362644a2 100644 --- a/Lib/test/.ruff.toml +++ b/Lib/test/.ruff.toml @@ -2,12 +2,12 @@ fix = true extend-exclude = [ # Excluded (run with the other AC files in its own separate ruff job in pre-commit) "test_clinic.py", +# Excluded (these aren't actually executed, they're just "data files") +"tokenizedata/*.py", # Failed to lint -"badsyntax_pep3120.py", "encoded_modules/module_iso_8859_1.py", "encoded_modules/module_koi8_r.py", # Failed to parse -"badsyntax_3131.py", "test_lib2to3/data/bom.py", "test_lib2to3/data/crlf.py", "test_lib2to3/data/different_encoding.py", diff --git a/Lib/test/test_utf8source.py b/Lib/test/test_utf8source.py index 97dced8a622889..c42b6b579d 100644 --- a/Lib/test/test_utf8source.py +++ b/Lib/test/test_utf8source.py @@ -1,5 +1,3 @@ -# This file is marked as binary in the CVS, to prevent MacCVS from recoding it. - import unittest class PEP3120Test(unittest.TestCase): @@ -16,7 +14,7 @@ def test_pep3120(self): def test_badsyntax(self): try: -import test.badsyntax_pep3120 +import test.tokenizedata.badsyntax_pep3120 except SyntaxError as msg: msg = str(msg).lower() self.assertTrue('utf-8' in msg) diff --git a/Lib/test/badsyntax_pep3120.py b/Lib/test/tokenizedata/badsyntax_pep3120.py similarity index 100% rename from Lib/test/badsyntax_pep3120.py rename to Lib/test/tokenizedata/badsyntax_pep3120.py ___ 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-117657: Use an atomic store to set type flags. (gh-127588)
https://github.com/python/cpython/commit/baae9cb159e240ee9474ce7c02f88c233390777a commit: baae9cb159e240ee9474ce7c02f88c233390777a branch: main author: Neil Schemenauer committer: nascheme date: 2025-02-25T21:24:20-08:00 summary: gh-117657: Use an atomic store to set type flags. (gh-127588) The `PyType_HasFeature()` function reads the flags with a relaxed atomic load and without holding the type lock. To avoid data races, use atomic stores if `PyType_Ready()` has already been called. files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 458d78e0502723..f667e56afbbf8b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -13,6 +13,7 @@ #include "pycore_moduleobject.h" // _PyModule_GetDef() #include "pycore_object.h"// _PyType_HasFeature() #include "pycore_object_alloc.h" // _PyObject_MallocWithType() +#include "pycore_pyatomic_ft_wrappers.h" #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // _Py_Mangle() @@ -344,6 +345,39 @@ _PyStaticType_GetBuiltins(void) /* end static builtin helpers */ +static void +type_set_flags(PyTypeObject *tp, unsigned long flags) +{ +if (tp->tp_flags & Py_TPFLAGS_READY) { +// It's possible the type object has been exposed to other threads +// if it's been marked ready. In that case, the type lock should be +// held when flags are modified. +ASSERT_TYPE_LOCK_HELD(); +} +// Since PyType_HasFeature() reads the flags without holding the type +// lock, we need an atomic store here. +FT_ATOMIC_STORE_ULONG_RELAXED(tp->tp_flags, flags); +} + +static void +type_set_flags_with_mask(PyTypeObject *tp, unsigned long mask, unsigned long flags) +{ +ASSERT_TYPE_LOCK_HELD(); +unsigned long new_flags = (tp->tp_flags & ~mask) | flags; +type_set_flags(tp, new_flags); +} + +static void +type_add_flags(PyTypeObject *tp, unsigned long flag) +{ +type_set_flags(tp, tp->tp_flags | flag); +} + +static void +type_clear_flags(PyTypeObject *tp, unsigned long flag) +{ +type_set_flags(tp, tp->tp_flags & ~flag); +} static inline void start_readying(PyTypeObject *type) @@ -357,7 +391,7 @@ start_readying(PyTypeObject *type) return; } assert((type->tp_flags & Py_TPFLAGS_READYING) == 0); -type->tp_flags |= Py_TPFLAGS_READYING; +type_add_flags(type, Py_TPFLAGS_READYING); } static inline void @@ -372,7 +406,7 @@ stop_readying(PyTypeObject *type) return; } assert(type->tp_flags & Py_TPFLAGS_READYING); -type->tp_flags &= ~Py_TPFLAGS_READYING; +type_clear_flags(type, Py_TPFLAGS_READYING); } static inline int @@ -1548,11 +1582,14 @@ type_set_abstractmethods(PyObject *tp, PyObject *value, void *Py_UNUSED(closure) return -1; } -PyType_Modified(type); +BEGIN_TYPE_LOCK(); +type_modified_unlocked(type); if (abstract) -type->tp_flags |= Py_TPFLAGS_IS_ABSTRACT; +type_add_flags(type, Py_TPFLAGS_IS_ABSTRACT); else -type->tp_flags &= ~Py_TPFLAGS_IS_ABSTRACT; +type_clear_flags(type, Py_TPFLAGS_IS_ABSTRACT); +END_TYPE_LOCK(); + return 0; } @@ -3335,7 +3372,7 @@ mro_internal_unlocked(PyTypeObject *type, int initial, PyObject **p_old_mro) // XXX Expand this to Py_TPFLAGS_IMMUTABLETYPE? if (!(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN)) { -PyType_Modified(type); +type_modified_unlocked(type); } else { /* For static builtin types, this is only called during init @@ -3941,8 +3978,8 @@ type_new_alloc(type_new_ctx *ctx) // Initialize tp_flags. // All heap types need GC, since we can create a reference cycle by storing // an instance on one of its parents. -type->tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | - Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC); +type_set_flags(type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | + Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC); // Initialize essential fields type->tp_as_async = &et->as_async; @@ -4175,12 +4212,12 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) if (ctx->add_weak) { assert((type->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF) == 0); -type->tp_flags |= Py_TPFLAGS_MANAGED_WEAKREF; +type_add_flags(type, Py_TPFLAGS_MANAGED_WEAKREF); type->tp_weaklistoffset = MANAGED_WEAKREF_OFFSET; } if (ctx->add_dict) { assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); -type->tp_flags |= Py_TPFLAGS_MANAGED_DICT; +type_add_flags(type, Py_TPFLAGS_MANAGED_DICT); type->tp_dictoffset = -1; } @@ -4978,7 +5015,7 @@ PyType_FromMetaclass( type = &res->ht_type; /* The flags must be initialized early, before the GC traverses us */ -type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTY
[Python-checkins] [3.13] gh-130163: Fix crashes related to PySys_GetObject() (GH-130503) (GH-130556)
https://github.com/python/cpython/commit/7c1b76fce8c8df00da38830f72dbdde6881a33be commit: 7c1b76fce8c8df00da38830f72dbdde6881a33be branch: 3.13 author: Serhiy Storchaka committer: serhiy-storchaka date: 2025-02-25T22:50:26Z summary: [3.13] gh-130163: Fix crashes related to PySys_GetObject() (GH-130503) (GH-130556) The use of PySys_GetObject() and _PySys_GetAttr(), which return a borrowed reference, has been replaced by using one of the following functions, which return a strong reference and distinguish a missing attribute from an error: _PySys_GetOptionalAttr(), _PySys_GetOptionalAttrString(), _PySys_GetRequiredAttr(), and _PySys_GetRequiredAttrString(). (cherry picked from commit 0ef4ffeefd1737c18dc9326133c7894d58108c2e) files: A Misc/NEWS.d/next/Core and Builtins/2025-02-24-14-25-36.gh-issue-130163.rGpc9v.rst M Include/internal/pycore_sysmodule.h M Lib/test/test_builtin.py M Lib/test/test_print.py M Lib/test/test_sys.py M Modules/_cursesmodule.c M Modules/_pickle.c M Modules/_threadmodule.c M Modules/_tkinter.c M Modules/faulthandler.c M Modules/syslogmodule.c M Objects/moduleobject.c M Python/_warnings.c M Python/bltinmodule.c M Python/ceval.c M Python/errors.c M Python/import.c M Python/initconfig.c M Python/intrinsics.c M Python/pylifecycle.c M Python/pythonrun.c M Python/sysmodule.c M Python/traceback.c diff --git a/Include/internal/pycore_sysmodule.h b/Include/internal/pycore_sysmodule.h index 9b8eafd3d6cfd3..6df574487bcd1b 100644 --- a/Include/internal/pycore_sysmodule.h +++ b/Include/internal/pycore_sysmodule.h @@ -8,8 +8,11 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -// Export for '_pickle' shared extension -PyAPI_FUNC(PyObject*) _PySys_GetAttr(PyThreadState *tstate, PyObject *name); +PyAPI_FUNC(PyObject *) _PySys_GetAttr(PyThreadState *, PyObject *); /* unused */ +PyAPI_FUNC(int) _PySys_GetOptionalAttr(PyObject *, PyObject **); +PyAPI_FUNC(int) _PySys_GetOptionalAttrString(const char *, PyObject **); +PyAPI_FUNC(PyObject *) _PySys_GetRequiredAttr(PyObject *); +PyAPI_FUNC(PyObject *) _PySys_GetRequiredAttrString(const char *); // Export for '_pickle' shared extension PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 3a5531924976f7..d4da29150d5fed 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1576,6 +1576,29 @@ def test_input(self): sys.stdout = savestdout fp.close() +def test_input_gh130163(self): +class X(io.StringIO): +def __getattribute__(self, name): +nonlocal patch +if patch: +patch = False +sys.stdout = X() +sys.stderr = X() +sys.stdin = X('input\n') +support.gc_collect() +return io.StringIO.__getattribute__(self, name) + +with (support.swap_attr(sys, 'stdout', None), + support.swap_attr(sys, 'stderr', None), + support.swap_attr(sys, 'stdin', None)): +patch = False +# the only references: +sys.stdout = X() +sys.stderr = X() +sys.stdin = X('input\n') +patch = True +input() # should not crash + # test_int(): see test_int.py for tests of built-in function int(). def test_repr(self): diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index 5f1bfd9e30db98..a782225ce99971 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -129,6 +129,17 @@ def flush(self): raise RuntimeError self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True) +def test_gh130163(self): +class X: +def __str__(self): +sys.stdout = StringIO() +support.gc_collect() +return 'foo' + +with support.swap_attr(sys, 'stdout', None): +sys.stdout = StringIO() # the only reference +print(X()) # should not crash + class TestPy2MigrationHint(unittest.TestCase): """Test that correct hint is produced analogous to Python3 syntax, diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 01ce0118651b75..19597eb75f9168 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -2,6 +2,7 @@ import codecs import _datetime import gc +import io import locale import operator import os @@ -80,6 +81,18 @@ def baddisplayhook(obj): code = compile("42", "", "single") self.assertRaises(ValueError, eval, code) +def test_gh130163(self): +class X: +def __repr__(self): +sys.stdout = io.StringIO() +support.gc_collect() +return 'foo' + +with support.swap_attr(sys, 'stdout', None): +sys.stdout = io.StringIO() # the only reference +sys.displayhook(X()) # should not cra
[Python-checkins] gh-129824: Temporarily skip InterpreterPoolMixin tests under TSAN (gh-129826)
https://github.com/python/cpython/commit/3774d9f7b56871372ac278e2c2d8ff33460d7eb0 commit: 3774d9f7b56871372ac278e2c2d8ff33460d7eb0 branch: main author: Sam Gross committer: colesbury date: 2025-02-25T10:33:04-05:00 summary: gh-129824: Temporarily skip InterpreterPoolMixin tests under TSAN (gh-129826) There are multiple data races reported when running the InterpreterPoolMixin tests, but it's still useful to run the other test_concurrent_futures tests under TSAN. Add test_concurrent_futures to the TSAN test suite. files: M Lib/test/libregrtest/tsan.py M Lib/test/test_concurrent_futures/util.py diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py index 2a656705d7b508..37d2983837fb78 100644 --- a/Lib/test/libregrtest/tsan.py +++ b/Lib/test/libregrtest/tsan.py @@ -6,6 +6,7 @@ 'test_capi.test_mem', 'test_capi.test_pyatomic', 'test_code', +'test_concurrent_futures', 'test_enum', 'test_functools', 'test_httpservers', diff --git a/Lib/test/test_concurrent_futures/util.py b/Lib/test/test_concurrent_futures/util.py index 52baab51340fc9..44086217f9dbcb 100644 --- a/Lib/test/test_concurrent_futures/util.py +++ b/Lib/test/test_concurrent_futures/util.py @@ -74,6 +74,7 @@ class ThreadPoolMixin(ExecutorMixin): executor_type = futures.ThreadPoolExecutor +@support.skip_if_sanitizer("gh-129824: data races in InterpreterPool tests", thread=True) class InterpreterPoolMixin(ExecutorMixin): executor_type = futures.InterpreterPoolExecutor ___ 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.13] Fix a typo in code module test (GH-130530) (#130534)
https://github.com/python/cpython/commit/b0d3f4919579cb02c46918f47ea4faa2e5d304fc commit: b0d3f4919579cb02c46918f47ea4faa2e5d304fc branch: 3.13 author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com> committer: gaogaotiantian date: 2025-02-25T17:38:40Z summary: [3.13] Fix a typo in code module test (GH-130530) (#130534) Fix a typo in code module test (GH-130530) (cherry picked from commit 56e337d32b88630f2c35458231cd61929f1be6d4) Co-authored-by: Tian Gao files: M Lib/test/test_code_module.py diff --git a/Lib/test/test_code_module.py b/Lib/test/test_code_module.py index 20b960ce8d1e02..faa0b38f8373e3 100644 --- a/Lib/test/test_code_module.py +++ b/Lib/test/test_code_module.py @@ -50,9 +50,9 @@ def test_ps2(self): self.infunc.side_effect = EOFError('Finished') self.console.interact() self.assertEqual(self.sysmod.ps2, '... ') -self.sysmod.ps1 = 'custom2> ' +self.sysmod.ps2 = 'custom2> ' self.console.interact() -self.assertEqual(self.sysmod.ps1, 'custom2> ') +self.assertEqual(self.sysmod.ps2, 'custom2> ') def test_console_stderr(self): self.infunc.side_effect = ["'antioch'", "", EOFError('Finished')] ___ 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-130396: Include stack margin for debug windows builds (GH-130554)
https://github.com/python/cpython/commit/2dad1e08ec9d5ddc798a313900613b3d1eeaff6b commit: 2dad1e08ec9d5ddc798a313900613b3d1eeaff6b branch: main author: Mark Shannon committer: markshannon date: 2025-02-25T19:26:21Z summary: GH-130396: Include stack margin for debug windows builds (GH-130554) files: M Include/pythonrun.h diff --git a/Include/pythonrun.h b/Include/pythonrun.h index ef4b727442a935..4d459cb92e36ea 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -28,7 +28,7 @@ PyAPI_DATA(int) (*PyOS_InputHook)(void); #if defined(_Py_ADDRESS_SANITIZER) || defined(_Py_THREAD_SANITIZER) # define PYOS_STACK_MARGIN 4096 #elif defined(Py_DEBUG) && defined(WIN32) -# define PYOS_STACK_MARGIN 3072 +# define PYOS_STACK_MARGIN 4096 #elif defined(__wasi__) /* Web assembly has two stacks, so this isn't really a size */ # define PYOS_STACK_MARGIN 500 ___ 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-130202: Fix bug in `_PyObject_ResurrectEnd` in free threaded build (gh-130281)
https://github.com/python/cpython/commit/f963239ff1f986742d4c6bab2ab7b73f5a4047f6 commit: f963239ff1f986742d4c6bab2ab7b73f5a4047f6 branch: main author: Sam Gross committer: colesbury date: 2025-02-25T12:03:28-05:00 summary: gh-130202: Fix bug in `_PyObject_ResurrectEnd` in free threaded build (gh-130281) This fixes a fairly subtle bug involving finalizers and resurrection in debug free threaded builds: if `_PyObject_ResurrectEnd` returns `1` (i.e., the object was resurrected by a finalizer), it's not safe to access the object because it might still be deallocated. For example: * The finalizer may have exposed the object to another thread. That thread may hold the last reference and concurrently deallocate it any time after `_PyObject_ResurrectEnd()` returns `1`. * `_PyObject_ResurrectEnd()` may call `_Py_brc_queue_object()`, which may internally deallocate the object immediately if the owning thread is dead. Therefore, it's important not to access the object after it's resurrected. We only violate this in two cases, and only in debug builds: * We assert that the object is tracked appropriately. This is now moved up betewen the finalizer and the `_PyObject_ResurrectEnd()` call. * The `--with-trace-refs` builds may need to remember the object if it's resurrected. This is now handled by `_PyObject_ResurrectStart()` and `_PyObject_ResurrectEnd()`. Note that `--with-trace-refs` is currently disabled in `--disable-gil` builds because the refchain hash table isn't thread-safe, but this refactoring avoids an additional thread-safety issue. files: M Include/cpython/object.h M Include/internal/pycore_object.h M Objects/object.c diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 260b90da24c18b..f466091e07e465 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -5,6 +5,7 @@ PyAPI_FUNC(void) _Py_NewReference(PyObject *op); PyAPI_FUNC(void) _Py_NewReferenceNoTotal(PyObject *op); PyAPI_FUNC(void) _Py_ResurrectReference(PyObject *op); +PyAPI_FUNC(void) _Py_ForgetReference(PyObject *op); #ifdef Py_REF_DEBUG /* These are useful as debugging aids when chasing down refleaks. */ diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index ffd31bd4a27f49..53403ebcfc0043 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -730,6 +730,9 @@ _PyObject_ResurrectStart(PyObject *op) #else Py_SET_REFCNT(op, 1); #endif +#ifdef Py_TRACE_REFS +_Py_ResurrectReference(op); +#endif } // Undoes an object resurrection by decrementing the refcount without calling @@ -743,13 +746,22 @@ _PyObject_ResurrectEnd(PyObject *op) #endif #ifndef Py_GIL_DISABLED Py_SET_REFCNT(op, Py_REFCNT(op) - 1); -return Py_REFCNT(op) != 0; +if (Py_REFCNT(op) == 0) { +# ifdef Py_TRACE_REFS +_Py_ForgetReference(op); +# endif +return 0; +} +return 1; #else uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); Py_ssize_t shared = _Py_atomic_load_ssize_acquire(&op->ob_ref_shared); if (_Py_IsOwnedByCurrentThread(op) && local == 1 && shared == 0) { // Fast-path: object has a single refcount and is owned by this thread _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, 0); +# ifdef Py_TRACE_REFS +_Py_ForgetReference(op); +# endif return 0; } // Slow-path: object has a shared refcount or is not owned by this thread diff --git a/Objects/object.c b/Objects/object.c index d342549b6ffecc..b3309bac7afdee 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -496,10 +496,22 @@ _PyObject_ResurrectEndSlow(PyObject *op) // merge the refcount. This isn't necessary in all cases, but it // simplifies the implementation. Py_ssize_t refcount = _Py_ExplicitMergeRefcount(op, -1); -return refcount != 0; +if (refcount == 0) { +#ifdef Py_TRACE_REFS +_Py_ForgetReference(op); +#endif +return 0; +} +return 1; } int is_dead = _Py_DecRefSharedIsDead(op, NULL, 0); -return !is_dead; +if (is_dead) { +#ifdef Py_TRACE_REFS +_Py_ForgetReference(op); +#endif +return 0; +} +return 1; } @@ -589,20 +601,24 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) Py_REFCNT(self) > 0, "refcount is too small"); +_PyObject_ASSERT(self, +(!_PyType_IS_GC(Py_TYPE(self)) +|| _PyObject_GC_IS_TRACKED(self))); + /* Undo the temporary resurrection; can't use DECREF here, it would * cause a recursive call. */ -if (!_PyObject_ResurrectEnd(self)) { -return 0; /* this is the normal path out */ +if (_PyObject_ResurrectEnd(self)) { +/* tp_finalize resurrected it! + gh-130202: Note that the object may still be dead in the free + threaded build in some circumstances,
[Python-checkins] [3.12] gh-130461: Remove unnecessary usages of `.. index::` directives in Doc/library/uuid.rst (#130526) (#130546)
https://github.com/python/cpython/commit/ca9e52dac15d0da4d4ef57fb408565338da0bb40 commit: ca9e52dac15d0da4d4ef57fb408565338da0bb40 branch: 3.12 author: Kanishk Pachauri committer: hugovk <1324225+hug...@users.noreply.github.com> date: 2025-02-25T15:25:20+02:00 summary: [3.12] gh-130461: Remove unnecessary usages of `.. index::` directives in Doc/library/uuid.rst (#130526) (#130546) Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hug...@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst M Doc/library/uuid.rst diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 0f2d7820cb25c8..95f1176e7512b8 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -179,8 +179,6 @@ The :mod:`uuid` module defines the following functions: administered MAC addresses, since the former are guaranteed to be globally unique, while the latter are not. -.. index:: single: getnode - .. function:: uuid1(node=None, clock_seq=None) @@ -189,8 +187,6 @@ The :mod:`uuid` module defines the following functions: *clock_seq* is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen. -.. index:: single: uuid1 - .. function:: uuid3(namespace, name) @@ -198,15 +194,11 @@ The :mod:`uuid` module defines the following functions: UUID) and a name (which is a :class:`bytes` object or a string that will be encoded using UTF-8). -.. index:: single: uuid3 - .. function:: uuid4() Generate a random UUID. -.. index:: single: uuid4 - .. function:: uuid5(namespace, name) @@ -214,7 +206,6 @@ The :mod:`uuid` module defines the following functions: UUID) and a name (which is a :class:`bytes` object or a string that will be encoded using UTF-8). -.. index:: single: uuid5 The :mod:`uuid` module defines the following namespace identifiers for use with :func:`uuid3` or :func:`uuid5`. diff --git a/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst b/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst new file mode 100644 index 00..d28f71fc1b1019 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst @@ -0,0 +1,4 @@ +Remove ``.. index::`` directives from the :mod:`uuid` module documentation. These directives +previously created entries in the general index for :func:`~uuid.getnode` as well as the +:func:`~uuid.uuid1`, :func:`~uuid.uuid3`, :func:`~uuid.uuid4`, and :func:`~uuid.uuid5` +constructor functions. ___ 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-130163: Fix crashes related to PySys_GetObject() (GH-130503)
https://github.com/python/cpython/commit/0ef4ffeefd1737c18dc9326133c7894d58108c2e commit: 0ef4ffeefd1737c18dc9326133c7894d58108c2e branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2025-02-25T23:04:27+02:00 summary: gh-130163: Fix crashes related to PySys_GetObject() (GH-130503) The use of PySys_GetObject() and _PySys_GetAttr(), which return a borrowed reference, has been replaced by using one of the following functions, which return a strong reference and distinguish a missing attribute from an error: _PySys_GetOptionalAttr(), _PySys_GetOptionalAttrString(), _PySys_GetRequiredAttr(), and _PySys_GetRequiredAttrString(). files: A Misc/NEWS.d/next/Core_and_Builtins/2025-02-24-14-25-36.gh-issue-130163.rGpc9v.rst M Include/internal/pycore_sysmodule.h M Lib/test/test_builtin.py M Lib/test/test_print.py M Lib/test/test_sys.py M Modules/_cursesmodule.c M Modules/_pickle.c M Modules/_threadmodule.c M Modules/_tkinter.c M Modules/faulthandler.c M Modules/syslogmodule.c M Objects/moduleobject.c M Python/_warnings.c M Python/bltinmodule.c M Python/ceval.c M Python/errors.c M Python/import.c M Python/initconfig.c M Python/intrinsics.c M Python/pylifecycle.c M Python/pythonrun.c M Python/sysmodule.c M Python/traceback.c diff --git a/Include/internal/pycore_sysmodule.h b/Include/internal/pycore_sysmodule.h index 99968df54a45f6..9536579e965f7b 100644 --- a/Include/internal/pycore_sysmodule.h +++ b/Include/internal/pycore_sysmodule.h @@ -8,8 +8,10 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -// Export for '_pickle' shared extension -PyAPI_FUNC(PyObject*) _PySys_GetAttr(PyThreadState *tstate, PyObject *name); +PyAPI_FUNC(int) _PySys_GetOptionalAttr(PyObject *, PyObject **); +PyAPI_FUNC(int) _PySys_GetOptionalAttrString(const char *, PyObject **); +PyAPI_FUNC(PyObject *) _PySys_GetRequiredAttr(PyObject *); +PyAPI_FUNC(PyObject *) _PySys_GetRequiredAttrString(const char *); // Export for '_pickle' shared extension PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index d707d9d2f20049..c3cc13614250f0 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1710,6 +1710,29 @@ def test_input(self): sys.stdout = savestdout fp.close() +def test_input_gh130163(self): +class X(io.StringIO): +def __getattribute__(self, name): +nonlocal patch +if patch: +patch = False +sys.stdout = X() +sys.stderr = X() +sys.stdin = X('input\n') +support.gc_collect() +return io.StringIO.__getattribute__(self, name) + +with (support.swap_attr(sys, 'stdout', None), + support.swap_attr(sys, 'stderr', None), + support.swap_attr(sys, 'stdin', None)): +patch = False +# the only references: +sys.stdout = X() +sys.stderr = X() +sys.stdin = X('input\n') +patch = True +input() # should not crash + # test_int(): see test_int.py for tests of built-in function int(). def test_repr(self): diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index f4805a1d6c6602..12256b3b562637 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -129,6 +129,17 @@ def flush(self): raise RuntimeError self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True) +def test_gh130163(self): +class X: +def __str__(self): +sys.stdout = StringIO() +support.gc_collect() +return 'foo' + +with support.swap_attr(sys, 'stdout', None): +sys.stdout = StringIO() # the only reference +print(X()) # should not crash + class TestPy2MigrationHint(unittest.TestCase): """Test that correct hint is produced analogous to Python3 syntax, diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 4a95fee7efb95c..87c0106ad30840 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -2,6 +2,7 @@ import codecs import _datetime import gc +import io import locale import operator import os @@ -80,6 +81,18 @@ def baddisplayhook(obj): code = compile("42", "", "single") self.assertRaises(ValueError, eval, code) +def test_gh130163(self): +class X: +def __repr__(self): +sys.stdout = io.StringIO() +support.gc_collect() +return 'foo' + +with support.swap_attr(sys, 'stdout', None): +sys.stdout = io.StringIO() # the only reference +sys.displayhook(X()) # should not crash + + class ActiveExceptionTests(unittest.TestCase): def test_exc_info_no_exception(self): self.assertEqual(sys.exc_info(), (None, None, None)) diff --
[Python-checkins] [3.12] gh-130151: Fix reference leaks in `_hashlib.hmac_{new,digest}` (GH-130152) (#130539)
https://github.com/python/cpython/commit/b1a188a7faa76949ef621a5ecac38b9fccae05cc commit: b1a188a7faa76949ef621a5ecac38b9fccae05cc branch: 3.12 author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-02-25T12:38:47+01:00 summary: [3.12] gh-130151: Fix reference leaks in `_hashlib.hmac_{new,digest}` (GH-130152) (#130539) gh-130151: Fix reference leaks in `_hashlib.hmac_{new,digest}` (GH-130152) * fix leak in `_hashlib.hmac_new` * fix leak in `hmac_digest` * fix exception type in `_hashlib.HMAC.copy` (cherry picked from commit 071820113f11b8f6a21f98652d0840e10268114c) files: A Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst M Modules/_hashopenssl.c diff --git a/Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst b/Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst new file mode 100644 index 00..4638f138bc43ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst @@ -0,0 +1,2 @@ +Fix reference leaks in :func:`!_hashlib.hmac_new` and +:func:`!_hashlib.hmac_digest`. Patch by Bénédikt Tran. diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 3cc7d6f50e896f..84afb743ab8c3b 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -1544,7 +1544,6 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, PyObject *digestmod) /*[clinic end generated code: output=c20d9e4d9ed6d219 input=5f4071dcc7f34362]*/ { -PyTypeObject *type = get_hashlib_state(module)->HMACtype; PY_EVP_MD *digest; HMAC_CTX *ctx = NULL; HMACobject *self = NULL; @@ -1557,8 +1556,8 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, } if (digestmod == NULL) { -PyErr_SetString( -PyExc_TypeError, "Missing required parameter 'digestmod'."); +PyErr_SetString(PyExc_TypeError, +"Missing required parameter 'digestmod'."); return NULL; } @@ -1569,40 +1568,37 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, ctx = HMAC_CTX_new(); if (ctx == NULL) { -_setException(PyExc_ValueError, NULL); +PyErr_NoMemory(); goto error; } -r = HMAC_Init_ex( -ctx, -(const char*)key->buf, -(int)key->len, -digest, -NULL /*impl*/); +r = HMAC_Init_ex(ctx, key->buf, (int)key->len, digest, NULL /* impl */); PY_EVP_MD_free(digest); if (r == 0) { _setException(PyExc_ValueError, NULL); goto error; } -self = (HMACobject *)PyObject_New(HMACobject, type); +_hashlibstate *state = get_hashlib_state(module); +self = PyObject_New(HMACobject, state->HMACtype); if (self == NULL) { goto error; } self->ctx = ctx; self->lock = NULL; +ctx = NULL; // 'ctx' is now owned by 'self' if ((msg_obj != NULL) && (msg_obj != Py_None)) { -if (!_hmac_update(self, msg_obj)) +if (!_hmac_update(self, msg_obj)) { goto error; +} } - -return (PyObject*)self; +return (PyObject *)self; error: if (ctx) HMAC_CTX_free(ctx); -if (self) PyObject_Free(self); +Py_XDECREF(self); return NULL; } @@ -1671,14 +1667,14 @@ _hashlib_HMAC_copy_impl(HMACobject *self) HMAC_CTX *ctx = HMAC_CTX_new(); if (ctx == NULL) { -return _setException(PyExc_ValueError, NULL); +return PyErr_NoMemory(); } if (!locked_HMAC_CTX_copy(ctx, self)) { HMAC_CTX_free(ctx); return _setException(PyExc_ValueError, NULL); } -retval = (HMACobject *)PyObject_New(HMACobject, Py_TYPE(self)); +retval = PyObject_New(HMACobject, Py_TYPE(self)); if (retval == NULL) { HMAC_CTX_free(ctx); return NULL; @@ -1696,7 +1692,10 @@ _hmac_dealloc(HMACobject *self) if (self->lock != NULL) { PyThread_free_lock(self->lock); } -HMAC_CTX_free(self->ctx); +if (self->ctx != NULL) { +HMAC_CTX_free(self->ctx); +self->ctx = NULL; +} PyObject_Free(self); Py_DECREF(tp); } @@ -1741,6 +1740,7 @@ _hmac_digest(HMACobject *self, unsigned char *buf, unsigned int len) return 0; } if (!locked_HMAC_CTX_copy(temp_ctx, self)) { +HMAC_CTX_free(temp_ctx); _setException(PyExc_ValueError, NULL); return 0; } ___ 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-87790: support thousands separators for formatting fractional part of floats (#125304)
https://github.com/python/cpython/commit/f39a07be47cd9219eaf0e538ae32ad8239c88e66 commit: f39a07be47cd9219eaf0e538ae32ad8239c88e66 branch: main author: Sergey B Kirpichev committer: vstinner date: 2025-02-25T16:27:07+01:00 summary: gh-87790: support thousands separators for formatting fractional part of floats (#125304) ```pycon >>> f"{123_456.123_456:_._f}" # Whole and fractional '123_456.123_456' >>> f"{123_456.123_456:_f}"# Integer component only '123_456.123456' >>> f"{123_456.123_456:._f}" # Fractional component only '123456.123_456' >>> f"{123_456.123_456:.4_f}" # with precision '123456.1_235' ``` files: A Misc/NEWS.d/next/Core_and_Builtins/2024-10-11-10-41-05.gh-issue-87790.mlfEGl.rst M Doc/library/string.rst M Doc/whatsnew/3.14.rst M Include/internal/pycore_unicodeobject.h M Lib/test/test_float.py M Lib/test/test_format.py M Objects/stringlib/localeutil.h M Objects/unicodeobject.c M Python/formatter_unicode.c diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 09165c481b246e..721c5c8d334674 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -319,14 +319,19 @@ non-empty format specification typically modifies the result. The general form of a *standard format specifier* is: .. productionlist:: format-spec - format_spec: [[`fill`]`align`][`sign`]["z"]["#"]["0"][`width`][`grouping_option`]["." `precision`][`type`] + format_spec: [`options`][`width_and_precision`][`type`] + options: [[`fill`]`align`][`sign`]["z"]["#"]["0"] fill: align: "<" | ">" | "=" | "^" sign: "+" | "-" | " " + width_and_precision: [`width_with_grouping`][`precision_with_grouping`] + width_with_grouping: [`width`][`grouping_option`] + precision_with_grouping: "." [`precision`]`grouping_option` width: `~python-grammar:digit`+ grouping_option: "_" | "," precision: `~python-grammar:digit`+ - type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" + type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" + : | "G" | "n" | "o" | "s" | "x" | "X" | "%" If a valid *align* value is specified, it can be preceded by a *fill* character that can be any character and defaults to a space if omitted. @@ -458,6 +463,13 @@ indicates the maximum field size - in other words, how many characters will be used from the field content. The *precision* is not allowed for integer presentation types. +The ``'_'`` or ``','`` option after *precision* means the use of an underscore +or a comma for a thousands separator of the fractional part for floating-point +presentation types. + +.. versionchanged:: 3.14 + Support thousands separators for the fractional part. + Finally, the *type* determines how the data should be presented. The available string presentation types are: @@ -704,10 +716,18 @@ Replacing ``%x`` and ``%o`` and converting the value to different bases:: >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42) 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010' -Using the comma as a thousands separator:: +Using the comma or the underscore as a thousands separator:: >>> '{:,}'.format(1234567890) '1,234,567,890' + >>> '{:_}'.format(1234567890) + '1_234_567_890' + >>> '{:_}'.format(123456789.123456789) + '123_456_789.12345679' + >>> '{:._}'.format(123456789.123456789) + '123456789.123_456_79' + >>> '{:_._}'.format(123456789.123456789) + '123_456_789.123_456_79' Expressing a percentage:: diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 1cd8da46a2bb7e..dbd59a9d7be150 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -336,6 +336,11 @@ Other language changes making it a :term:`generic type`. (Contributed by Brian Schubert in :gh:`126012`.) +* Support underscore and comma as thousands separators in the fractional part + for floating-point presentation types of the new-style string formatting + (with :func:`format` or :ref:`f-strings`). + (Contrubuted by Sergey B Kirpichev in :gh:`87790`.) + * ``\B`` in :mod:`regular expression ` now matches empty input string. Now it is always the opposite of ``\b``. (Contributed by Serhiy Storchaka in :gh:`124130`.) diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index a60372f58295a9..13c3213132568b 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -246,7 +246,8 @@ extern Py_ssize_t _PyUnicode_InsertThousandsGrouping( Py_ssize_t min_width, const char *grouping, PyObject *thousands_sep, -Py_UCS4 *maxchar); +Py_UCS4 *maxchar, +int forward); /* --- Misc functions - */ diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index f588e16b70123a..231b1047f72b39 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -754,6 +754,28 @@ def test_format(self): self.assertEqua
[Python-checkins] gh-122029: Move monitoring after method expand for CALL_KW (GH-130488)
https://github.com/python/cpython/commit/c5f925c8c948736bd64652918b4e0186b91abbb5 commit: c5f925c8c948736bd64652918b4e0186b91abbb5 branch: main author: Tian Gao committer: markshannon date: 2025-02-25T15:43:49Z summary: gh-122029: Move monitoring after method expand for CALL_KW (GH-130488) files: A Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst M Lib/test/test_sys_setprofile.py M Python/bytecodes.c M Python/generated_cases.c.h diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py index 311a4d2cafe88d..0753a9d8b8e0ee 100644 --- a/Lib/test/test_sys_setprofile.py +++ b/Lib/test/test_sys_setprofile.py @@ -493,6 +493,24 @@ class A: # The last c_call is the call to sys.setprofile self.assertEqual(events, ['c_call', 'c_return', 'c_call']) +class B: +f = classmethod(max) +events = [] +sys.setprofile(lambda frame, event, args: events.append(event)) +# Not important, we only want to trigger INSTRUMENTED_CALL_KW +B().f(1, key=lambda x: 0) +sys.setprofile(None) +# The last c_call is the call to sys.setprofile +self.assertEqual( +events, +['c_call', + 'call', 'return', + 'call', 'return', + 'c_return', + 'c_call' +] +) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst new file mode 100644 index 00..ec7d774a16fdb0 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst @@ -0,0 +1 @@ +``INSTRUMENTED_CALL_KW`` will expand the method before monitoring to reflect the actual behavior more accurately. diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 3c5cb07709d66c..6f91b10b8b8a9b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4509,8 +4509,8 @@ dummy_func( macro(INSTRUMENTED_CALL_KW) = counter/1 + unused/2 + -_MONITOR_CALL_KW + _MAYBE_EXPAND_METHOD_KW + +_MONITOR_CALL_KW + _DO_CALL_KW; op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable[1], unused[1], unused[oparg], kwnames -- callable[1], unused[1], unused[oparg], kwnames)) { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 268e8836994bc4..377be6fb6d6390 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -6413,14 +6413,37 @@ _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; -_PyStackRef kwnames; _PyStackRef kwnames_in; _PyStackRef *func; _PyStackRef *maybe_self; _PyStackRef kwnames_out; +_PyStackRef kwnames; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ +// _MAYBE_EXPAND_METHOD_KW +{ +kwnames_in = stack_pointer[-1]; +args = &stack_pointer[-1 - oparg]; +self_or_null = &stack_pointer[-2 - oparg]; +callable = &stack_pointer[-3 - oparg]; +func = &stack_pointer[-3 - oparg]; +maybe_self = &stack_pointer[-2 - oparg]; +args = &stack_pointer[-1 - oparg]; +(void)args; +if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { +PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); +PyObject *self = ((PyMethodObject *)callable_o)->im_self; +maybe_self[0] = PyStackRef_FromPyObjectNew(self); +PyObject *method = ((PyMethodObject *)callable_o)->im_func; +_PyStackRef temp = callable[0]; +func[0] = PyStackRef_FromPyObjectNew(method); +_PyFrame_SetStackPointer(frame, stack_pointer); +PyStackRef_CLOSE(temp); +stack_pointer = _PyFrame_GetStackPointer(frame); +} +kwnames_out = kwnames_in; +} // _MONITOR_CALL_KW { args = &stack_pointer[-1 - oparg]; @@ -6440,6 +6463,7 @@ } } PyObject *function = PyStackRef_AsPyObjectBorrow(callable[0]); +stack_pointer[-1] = kwnames_out; _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, @@ -6449,32 +6473,9 @@ JUMP_TO_LABEL(error); } } -// _MAYBE_EXPAND_METHOD_KW -{ -k
[Python-checkins] gh-130461: Remove unnecessary usages of `.. index::` directives in Doc/library/uuid.rst (#130526)
https://github.com/python/cpython/commit/85f1cc8d60b06d5b2af3e4da8e4f98171420dd91 commit: 85f1cc8d60b06d5b2af3e4da8e4f98171420dd91 branch: main author: Kanishk Pachauri committer: hugovk <1324225+hug...@users.noreply.github.com> date: 2025-02-25T14:27:50+02:00 summary: gh-130461: Remove unnecessary usages of `.. index::` directives in Doc/library/uuid.rst (#130526) Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst M Doc/library/uuid.rst diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index bff6b9dcdc57ca..c661fa2e52565c 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -184,8 +184,6 @@ The :mod:`uuid` module defines the following functions: administered MAC addresses, since the former are guaranteed to be globally unique, while the latter are not. -.. index:: single: getnode - .. function:: uuid1(node=None, clock_seq=None) @@ -194,8 +192,6 @@ The :mod:`uuid` module defines the following functions: *clock_seq* is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen. -.. index:: single: uuid1 - .. function:: uuid3(namespace, name) @@ -203,15 +199,11 @@ The :mod:`uuid` module defines the following functions: UUID) and a name (which is a :class:`bytes` object or a string that will be encoded using UTF-8). -.. index:: single: uuid3 - .. function:: uuid4() Generate a random UUID. -.. index:: single: uuid4 - .. function:: uuid5(namespace, name) @@ -219,8 +211,6 @@ The :mod:`uuid` module defines the following functions: UUID) and a name (which is a :class:`bytes` object or a string that will be encoded using UTF-8). -.. index:: single: uuid5 - .. function:: uuid8(a=None, b=None, c=None) @@ -235,8 +225,6 @@ The :mod:`uuid` module defines the following functions: .. versionadded:: 3.14 -.. index:: single: uuid8 - The :mod:`uuid` module defines the following namespace identifiers for use with :func:`uuid3` or :func:`uuid5`. diff --git a/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst b/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst new file mode 100644 index 00..9e7e0373ea43a4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst @@ -0,0 +1,4 @@ +Remove ``.. index::`` directives from the :mod:`uuid` module documentation. These directives +previously created entries in the general index for :func:`~uuid.getnode` as well as the +:func:`~uuid.uuid1`, :func:`~uuid.uuid3`, :func:`~uuid.uuid4`, :func:`~uuid.uuid5`, and +:func:`~uuid.uuid8` constructor functions. ___ 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-111178: fix UBSan failures in `Modules/xx*.c` (GH-129797)
https://github.com/python/cpython/commit/ead091357d67bc8144a73fcb7cb367602d21ecdd commit: ead091357d67bc8144a73fcb7cb367602d21ecdd branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: encukou date: 2025-02-25T13:02:32+01:00 summary: gh-78: fix UBSan failures in `Modules/xx*.c` (GH-129797) Fix UBSan failures in `Modules/xxlimited.c`, `Modules/xxlimited_35.c`, `Modules/xxsubtype.c`, `Modules/xxmodule.c` files: M Modules/xxlimited.c M Modules/xxlimited_35.c M Modules/xxmodule.c M Modules/xxsubtype.c diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index d86741e1dfc18c..26ac35734fb060 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -90,6 +90,7 @@ typedef struct { Py_ssize_t x_exports; /* how many buffer are exported */ } XxoObject; +#define XxoObject_CAST(op) ((XxoObject *)(op)) // XXX: no good way to do this yet // #define XxoObject_Check(v) Py_IS_TYPE(v, Xxo_Type) @@ -114,28 +115,29 @@ newXxoObject(PyObject *module) /* Xxo finalization */ static int -Xxo_traverse(PyObject *self_obj, visitproc visit, void *arg) +Xxo_traverse(PyObject *op, visitproc visit, void *arg) { // Visit the type -Py_VISIT(Py_TYPE(self_obj)); +Py_VISIT(Py_TYPE(op)); // Visit the attribute dict -XxoObject *self = (XxoObject *)self_obj; +XxoObject *self = XxoObject_CAST(op); Py_VISIT(self->x_attr); return 0; } static int -Xxo_clear(XxoObject *self) +Xxo_clear(PyObject *op) { +XxoObject *self = XxoObject_CAST(op); Py_CLEAR(self->x_attr); return 0; } static void -Xxo_finalize(PyObject *self_obj) +Xxo_finalize(PyObject *op) { -XxoObject *self = (XxoObject *)self_obj; +XxoObject *self = XxoObject_CAST(op); Py_CLEAR(self->x_attr); } @@ -154,8 +156,9 @@ Xxo_dealloc(PyObject *self) /* Xxo attribute handling */ static PyObject * -Xxo_getattro(XxoObject *self, PyObject *name) +Xxo_getattro(PyObject *op, PyObject *name) { +XxoObject *self = XxoObject_CAST(op); if (self->x_attr != NULL) { PyObject *v = PyDict_GetItemWithError(self->x_attr, name); if (v != NULL) { @@ -165,12 +168,13 @@ Xxo_getattro(XxoObject *self, PyObject *name) return NULL; } } -return PyObject_GenericGetAttr((PyObject *)self, name); +return PyObject_GenericGetAttr(op, name); } static int -Xxo_setattro(XxoObject *self, PyObject *name, PyObject *v) +Xxo_setattro(PyObject *op, PyObject *name, PyObject *v) { +XxoObject *self = XxoObject_CAST(op); if (self->x_attr == NULL) { // prepare the attribute dict self->x_attr = PyDict_New(); @@ -197,8 +201,8 @@ Xxo_setattro(XxoObject *self, PyObject *name, PyObject *v) /* Xxo methods */ static PyObject * -Xxo_demo(XxoObject *self, PyTypeObject *defining_class, - PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +Xxo_demo(PyObject *op, PyTypeObject *defining_class, + PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { if (kwnames != NULL && PyObject_Length(kwnames)) { PyErr_SetString(PyExc_TypeError, "demo() takes no keyword arguments"); @@ -233,9 +237,10 @@ static PyMethodDef Xxo_methods[] = { /* Xxo buffer interface */ static int -Xxo_getbuffer(XxoObject *self, Py_buffer *view, int flags) +Xxo_getbuffer(PyObject *op, Py_buffer *view, int flags) { -int res = PyBuffer_FillInfo(view, (PyObject*)self, +XxoObject *self = XxoObject_CAST(op); +int res = PyBuffer_FillInfo(view, op, (void *)self->x_buffer, BUFSIZE, 0, flags); if (res == 0) { @@ -245,14 +250,16 @@ Xxo_getbuffer(XxoObject *self, Py_buffer *view, int flags) } static void -Xxo_releasebuffer(XxoObject *self, Py_buffer *view) +Xxo_releasebuffer(PyObject *op, Py_buffer *Py_UNUSED(view)) { +XxoObject *self = XxoObject_CAST(op); self->x_exports--; } static PyObject * -Xxo_get_x_exports(XxoObject *self, void *c) +Xxo_get_x_exports(PyObject *op, void *Py_UNUSED(closure)) { +XxoObject *self = XxoObject_CAST(op); return PyLong_FromSsize_t(self->x_exports); } @@ -262,7 +269,7 @@ PyDoc_STRVAR(Xxo_doc, "A class that explicitly stores attributes in an internal dict"); static PyGetSetDef Xxo_getsetlist[] = { -{"x_exports", (getter) Xxo_get_x_exports, NULL, NULL}, +{"x_exports", Xxo_get_x_exports, NULL, NULL}, {NULL}, }; diff --git a/Modules/xxlimited_35.c b/Modules/xxlimited_35.c index 1063e54217b746..48fd1aac3f0f8d 100644 --- a/Modules/xxlimited_35.c +++ b/Modules/xxlimited_35.c @@ -24,7 +24,8 @@ typedef struct { static PyObject *Xxo_Type; -#define XxoObject_Check(v) Py_IS_TYPE(v, Xxo_Type) +#define XxoObject_CAST(op) ((XxoObject *)(op)) +#define XxoObject_Check(v) Py_IS_TYPE(v, Xxo_Type) static XxoObject * newXxoObject(PyObject *arg) @@ -40,32 +41,36 @@ newXxoObject(PyObject *arg) /* Xxo methods */ static i
[Python-checkins] gh-111178: fix UBSan failures in `Objects/typevarobject.c` (GH-129800)
https://github.com/python/cpython/commit/ecde9400254eabf0ebcdbb04cb266e50f126e8ec commit: ecde9400254eabf0ebcdbb04cb266e50f126e8ec branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: encukou date: 2025-02-25T13:12:47+01:00 summary: gh-78: fix UBSan failures in `Objects/typevarobject.c` (GH-129800) Fix UBSan failures for `typealiasobject`, `paramspecobject`, `typevarobject`, `typevartupleobject`, `paramspecattrobject` Use _PyCFunction_CAST macros Use macro for `constevaluatorobject` casts files: M Objects/typevarobject.c diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 4ed40aa71a595e..d8158293acaabd 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -57,6 +57,11 @@ typedef struct { PyObject *module; } typealiasobject; +#define typevarobject_CAST(op) ((typevarobject *)(op)) +#define typevartupleobject_CAST(op) ((typevartupleobject *)(op)) +#define paramspecobject_CAST(op)((paramspecobject *)(op)) +#define typealiasobject_CAST(op)((typealiasobject *)(op)) + #include "clinic/typevarobject.c.h" /* NoDefault is a marker object to indicate that a parameter has no default. */ @@ -121,11 +126,13 @@ typedef struct { PyObject *value; } constevaluatorobject; +#define constevaluatorobject_CAST(op) ((constevaluatorobject *)(op)) + static void constevaluator_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); -constevaluatorobject *ce = (constevaluatorobject *)self; +constevaluatorobject *ce = constevaluatorobject_CAST(self); _PyObject_GC_UNTRACK(self); @@ -138,7 +145,7 @@ constevaluator_dealloc(PyObject *self) static int constevaluator_traverse(PyObject *self, visitproc visit, void *arg) { -constevaluatorobject *ce = (constevaluatorobject *)self; +constevaluatorobject *ce = constevaluatorobject_CAST(self); Py_VISIT(ce->value); return 0; } @@ -146,20 +153,22 @@ constevaluator_traverse(PyObject *self, visitproc visit, void *arg) static int constevaluator_clear(PyObject *self) { -Py_CLEAR(((constevaluatorobject *)self)->value); +constevaluatorobject *ce = constevaluatorobject_CAST(self); +Py_CLEAR(ce->value); return 0; } static PyObject * constevaluator_repr(PyObject *self) { -PyObject *value = ((constevaluatorobject *)self)->value; -return PyUnicode_FromFormat("", value); +constevaluatorobject *ce = constevaluatorobject_CAST(self); +return PyUnicode_FromFormat("", ce->value); } static PyObject * constevaluator_call(PyObject *self, PyObject *args, PyObject *kwargs) { +constevaluatorobject *ce = constevaluatorobject_CAST(self); if (!_PyArg_NoKeywords("constevaluator.__call__", kwargs)) { return NULL; } @@ -167,7 +176,7 @@ constevaluator_call(PyObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTuple(args, "i:constevaluator.__call__", &format)) { return NULL; } -PyObject *value = ((constevaluatorobject *)self)->value; +PyObject *value = ce->value; if (format == _Py_ANNOTATE_FORMAT_STRING) { PyUnicodeWriter *writer = PyUnicodeWriter_Create(5); // cannot be <5 if (writer == NULL) { @@ -453,7 +462,7 @@ static void typevar_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); -typevarobject *tv = (typevarobject *)self; +typevarobject *tv = typevarobject_CAST(self); _PyObject_GC_UNTRACK(self); @@ -475,7 +484,7 @@ static int typevar_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); -typevarobject *tv = (typevarobject *)self; +typevarobject *tv = typevarobject_CAST(self); Py_VISIT(tv->bound); Py_VISIT(tv->evaluate_bound); Py_VISIT(tv->constraints); @@ -487,22 +496,23 @@ typevar_traverse(PyObject *self, visitproc visit, void *arg) } static int -typevar_clear(typevarobject *self) +typevar_clear(PyObject *op) { +typevarobject *self = typevarobject_CAST(op); Py_CLEAR(self->bound); Py_CLEAR(self->evaluate_bound); Py_CLEAR(self->constraints); Py_CLEAR(self->evaluate_constraints); Py_CLEAR(self->default_value); Py_CLEAR(self->evaluate_default); -PyObject_ClearManagedDict((PyObject *)self); +PyObject_ClearManagedDict(op); return 0; } static PyObject * typevar_repr(PyObject *self) { -typevarobject *tv = (typevarobject *)self; +typevarobject *tv = typevarobject_CAST(self); if (tv->infer_variance) { return Py_NewRef(tv->name); @@ -521,8 +531,9 @@ static PyMemberDef typevar_members[] = { }; static PyObject * -typevar_bound(typevarobject *self, void *Py_UNUSED(ignored)) +typevar_bound(PyObject *op, void *Py_UNUSED(closure)) { +typevarobject *self = typevarobject_CAST(op); if (self->bound != NULL) { return Py_NewRef(self->bound); } @@ -535,8 +546,9 @@ typevar_bound(typevarobject *self, void *Py_UNUSED(ignored)) } static PyObject * -ty
[Python-checkins] gh-111178: fix UBSan failures in `Modules/unicodedata.c` (GH-129801)
https://github.com/python/cpython/commit/c1478d1ebb7a6331d06939a27618dafb7fce91f1 commit: c1478d1ebb7a6331d06939a27618dafb7fce91f1 branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: encukou date: 2025-02-25T13:13:47+01:00 summary: gh-78: fix UBSan failures in `Modules/unicodedata.c` (GH-129801) fix UBSan failures for `PreviousDBVersion` files: M Modules/unicodedata.c diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 79be7674fc8ab5..f1ff7bd3eba232 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -77,9 +77,11 @@ typedef struct previous_version { Py_UCS4 (*normalization)(Py_UCS4); } PreviousDBVersion; +#define PreviousDBVersion_CAST(op) ((PreviousDBVersion *)(op)) + #include "clinic/unicodedata.c.h" -#define get_old_record(self, v)PreviousDBVersion*)self)->getrecord)(v)) +#define get_old_record(self, v)(PreviousDBVersion_CAST(self)->getrecord(v)) static PyMemberDef DB_members[] = { {"unidata_version", Py_T_STRING, offsetof(PreviousDBVersion, name), Py_READONLY}, @@ -1591,14 +1593,14 @@ static PyMethodDef unicodedata_functions[] = { }; static int -ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg) +ucd_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); return 0; } static void -ucd_dealloc(PreviousDBVersion *self) +ucd_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); ___ 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.13] gh-130461: Remove unnecessary usages of `.. index::` directives in Doc/library/uuid.rst (#130526) (#130548)
https://github.com/python/cpython/commit/28bfc1c99698cb36491ffa146d478b05da8467ce commit: 28bfc1c99698cb36491ffa146d478b05da8467ce branch: 3.13 author: Kanishk Pachauri committer: hugovk <1324225+hug...@users.noreply.github.com> date: 2025-02-25T15:24:46+02:00 summary: [3.13] gh-130461: Remove unnecessary usages of `.. index::` directives in Doc/library/uuid.rst (#130526) (#130548) Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst M Doc/library/uuid.rst diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 0f2d7820cb25c8..95f1176e7512b8 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -179,8 +179,6 @@ The :mod:`uuid` module defines the following functions: administered MAC addresses, since the former are guaranteed to be globally unique, while the latter are not. -.. index:: single: getnode - .. function:: uuid1(node=None, clock_seq=None) @@ -189,8 +187,6 @@ The :mod:`uuid` module defines the following functions: *clock_seq* is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen. -.. index:: single: uuid1 - .. function:: uuid3(namespace, name) @@ -198,15 +194,11 @@ The :mod:`uuid` module defines the following functions: UUID) and a name (which is a :class:`bytes` object or a string that will be encoded using UTF-8). -.. index:: single: uuid3 - .. function:: uuid4() Generate a random UUID. -.. index:: single: uuid4 - .. function:: uuid5(namespace, name) @@ -214,7 +206,6 @@ The :mod:`uuid` module defines the following functions: UUID) and a name (which is a :class:`bytes` object or a string that will be encoded using UTF-8). -.. index:: single: uuid5 The :mod:`uuid` module defines the following namespace identifiers for use with :func:`uuid3` or :func:`uuid5`. diff --git a/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst b/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst new file mode 100644 index 00..d28f71fc1b1019 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-25-03-53-00.gh-issue-130461.asr2dg.rst @@ -0,0 +1,4 @@ +Remove ``.. index::`` directives from the :mod:`uuid` module documentation. These directives +previously created entries in the general index for :func:`~uuid.getnode` as well as the +:func:`~uuid.uuid1`, :func:`~uuid.uuid3`, :func:`~uuid.uuid4`, and :func:`~uuid.uuid5` +constructor functions. ___ 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-129173: refactor `PyCodec_ReplaceErrors` into separate functions (#129893)
https://github.com/python/cpython/commit/fa6a8140dd2a72da6df2a7dfafbf07045debf64d commit: fa6a8140dd2a72da6df2a7dfafbf07045debf64d branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-02-25T14:24:46+01:00 summary: gh-129173: refactor `PyCodec_ReplaceErrors` into separate functions (#129893) The logic of `PyCodec_ReplaceErrors` is now split into separate functions, each of which handling a specific exception type. files: M Python/codecs.c diff --git a/Python/codecs.c b/Python/codecs.c index be019d6cda52a7..b876b816f688a0 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -730,6 +730,27 @@ codec_handler_write_unicode_hex(Py_UCS1 **p, Py_UCS4 ch) } +/* + * Create a Unicode string containing 'count' copies of the official + * Unicode REPLACEMENT CHARACTER (0xFFFD). + */ +static PyObject * +codec_handler_unicode_replacement_character(Py_ssize_t count) +{ +PyObject *res = PyUnicode_New(count, Py_UNICODE_REPLACEMENT_CHARACTER); +if (res == NULL) { +return NULL; +} +assert(count == 0 || PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND); +Py_UCS2 *outp = PyUnicode_2BYTE_DATA(res); +for (Py_ssize_t i = 0; i < count; ++i) { +outp[i] = Py_UNICODE_REPLACEMENT_CHARACTER; +} +assert(_PyUnicode_CheckConsistency(res, 1)); +return res; +} + + // --- handler: 'strict' -- PyObject *PyCodec_StrictErrors(PyObject *exc) @@ -774,50 +795,71 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) } -PyObject *PyCodec_ReplaceErrors(PyObject *exc) +// --- handler: 'replace' - + +static PyObject * +_PyCodec_ReplaceUnicodeEncodeError(PyObject *exc) { Py_ssize_t start, end, slen; +if (_PyUnicodeError_GetParams(exc, NULL, NULL, + &start, &end, &slen, false) < 0) +{ +return NULL; +} +PyObject *res = PyUnicode_New(slen, '?'); +if (res == NULL) { +return NULL; +} +assert(PyUnicode_KIND(res) == PyUnicode_1BYTE_KIND); +Py_UCS1 *outp = PyUnicode_1BYTE_DATA(res); +memset(outp, '?', sizeof(Py_UCS1) * slen); +assert(_PyUnicode_CheckConsistency(res, 1)); +return Py_BuildValue("(Nn)", res, end); +} -if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { -if (_PyUnicodeError_GetParams(exc, NULL, NULL, - &start, &end, &slen, false) < 0) { -return NULL; -} -PyObject *res = PyUnicode_New(slen, '?'); -if (res == NULL) { -return NULL; -} -assert(PyUnicode_KIND(res) == PyUnicode_1BYTE_KIND); -Py_UCS1 *outp = PyUnicode_1BYTE_DATA(res); -memset(outp, '?', sizeof(Py_UCS1) * slen); -assert(_PyUnicode_CheckConsistency(res, 1)); -return Py_BuildValue("(Nn)", res, end); + +static PyObject * +_PyCodec_ReplaceUnicodeDecodeError(PyObject *exc) +{ +Py_ssize_t end; +if (PyUnicodeDecodeError_GetEnd(exc, &end) < 0) { +return NULL; } -else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { -if (_PyUnicodeError_GetParams(exc, NULL, NULL, - NULL, &end, NULL, true) < 0) { -return NULL; -} -return Py_BuildValue("(Cn)", - (int)Py_UNICODE_REPLACEMENT_CHARACTER, - end); +PyObject *res = codec_handler_unicode_replacement_character(1); +if (res == NULL) { +return NULL; } -else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { -if (_PyUnicodeError_GetParams(exc, NULL, NULL, - &start, &end, &slen, false) < 0) { -return NULL; -} -PyObject *res = PyUnicode_New(slen, Py_UNICODE_REPLACEMENT_CHARACTER); -if (res == NULL) { -return NULL; -} -assert(slen == 0 || PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND); -Py_UCS2 *outp = PyUnicode_2BYTE_DATA(res); -for (Py_ssize_t i = 0; i < slen; ++i) { -outp[i] = Py_UNICODE_REPLACEMENT_CHARACTER; -} -assert(_PyUnicode_CheckConsistency(res, 1)); -return Py_BuildValue("(Nn)", res, end); +return Py_BuildValue("(Nn)", res, end); +} + + +static PyObject * +_PyCodec_ReplaceUnicodeTranslateError(PyObject *exc) +{ +Py_ssize_t start, end, slen; +if (_PyUnicodeError_GetParams(exc, NULL, NULL, + &start, &end, &slen, false) < 0) +{ +return NULL; +} +PyObject *res = codec_handler_unicode_replacement_character(slen); +if (res == NULL) { +return NULL; +} +return Py_BuildValue("(Nn)", res, end); +} + + +PyObject *PyCodec_ReplaceErrors(PyObject *exc) +{ +if (_PyIsUnicodeEncodeE
[Python-checkins] Docs: Fix some semantic usages of `iterator.__iter__` (GH-130172)
https://github.com/python/cpython/commit/4d3a7ea354a8ca7a9978f48e54399526d1b83f42 commit: 4d3a7ea354a8ca7a9978f48e54399526d1b83f42 branch: main author: Yuki Kobayashi committer: encukou date: 2025-02-25T13:38:47+01:00 summary: Docs: Fix some semantic usages of `iterator.__iter__` (GH-130172) These references to an `__iter__` method mean `object.__iter__`, not `iterator.__iter__`. files: M Doc/glossary.rst M Doc/library/abc.rst M Doc/library/stdtypes.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 7670bd859e282e..a6b94b564db177 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -719,7 +719,7 @@ Glossary iterables include all sequence types (such as :class:`list`, :class:`str`, and :class:`tuple`) and some non-sequence types like :class:`dict`, :term:`file objects `, and objects of any classes you define - with an :meth:`~iterator.__iter__` method or with a + with an :meth:`~object.__iter__` method or with a :meth:`~object.__getitem__` method that implements :term:`sequence` semantics. diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 38d744e97d087d..49e541a9d9b1cb 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -141,18 +141,18 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: MyIterable.register(Foo) The ABC ``MyIterable`` defines the standard iterable method, - :meth:`~iterator.__iter__`, as an abstract method. The implementation given + :meth:`~object.__iter__`, as an abstract method. The implementation given here can still be called from subclasses. The :meth:`!get_iterator` method is also part of the ``MyIterable`` abstract base class, but it does not have to be overridden in non-abstract derived classes. The :meth:`__subclasshook__` class method defined here says that any class - that has an :meth:`~iterator.__iter__` method in its + that has an :meth:`~object.__iter__` method in its :attr:`~object.__dict__` (or in that of one of its base classes, accessed via the :attr:`~type.__mro__` list) is considered a ``MyIterable`` too. Finally, the last line makes ``Foo`` a virtual subclass of ``MyIterable``, - even though it does not define an :meth:`~iterator.__iter__` method (it uses + even though it does not define an :meth:`~object.__iter__` method (it uses the old-style iterable protocol, defined in terms of :meth:`~object.__len__` and :meth:`~object.__getitem__`). Note that this will not make ``get_iterator`` available as a method of ``Foo``, so it is provided separately. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 143fc6508ebc42..0564981b52e4f0 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -949,9 +949,9 @@ Generator Types --- Python's :term:`generator`\s provide a convenient way to implement the iterator -protocol. If a container object's :meth:`~iterator.__iter__` method is implemented as a +protocol. If a container object's :meth:`~object.__iter__` method is implemented as a generator, it will automatically return an iterator object (technically, a -generator object) supplying the :meth:`!__iter__` and :meth:`~generator.__next__` +generator object) supplying the :meth:`~iterator.__iter__` and :meth:`~generator.__next__` methods. More information about generators can be found in :ref:`the documentation for the yield expression `. ___ 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