8000 Merge branch 'main' into gh-100141 · SonOfLilit/cpython@e5b1d00 · GitHub
[go: up one dir, main page]

Skip to content

Commit e5b1d00

Browse files
authored
Merge branch 'main' into pythongh-100141
2 parents c2d17cc + 99b00ef commit e5b1d00

21 files changed

+216
-64
lines changed

Doc/library/doctest.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,10 @@ Simple example::
409409
>>> [1, 2, 3].remove(42)
410410
Traceback (most recent call last):
411411
File "<stdin>", line 1, in <module>
412-
ValueError: list.remove(x): x not in list
412+
ValueError: 42 is not in list
413413

414-
That doctest succeeds if :exc:`ValueError` is raised, with the ``list.remove(x):
415-
x not in list`` detail as shown.
414+
That doctest succeeds if :exc:`ValueError` is raised, with the ``42 is not in list``
415+
detail as shown.
416416

417417
The expected output for an exception must start with a traceback header, which
418418
may be either of the following two lines, indented the same as the first line of

Doc/library/exceptions.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,8 @@ The following exceptions are used as warning categories; see the
871871
.. versionadded:: 3.2
872872

873873

874+
.. _lib-exception-groups:
875+
874876
Exception groups
875877
----------------
876878

Doc/library/shlex.rst

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ The :mod:`shlex` module defines the following functions:
3030
in POSIX mode by default, but uses non-POSIX mode if the *posix* argument is
3131
false.
3232

33-
.. note::
34-
35-
Since the :func:`split` function instantiates a :class:`~shlex.shlex`
36-
instance, passing ``None`` for *s* will read the string to split from
37-
standard input.
38-
3933
.. versionchanged:: 3.12
4034
Passing ``None`` for *s* argument now raises an exception, rather than
4135
reading :data:`sys.stdin`.

Doc/tutorial/errors.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,8 @@ the following pattern::
578578
...
579579

580580

581+
.. _tut-exception-notes:
582+
581583
Enriching Exceptions with Notes
582584
===============================
583585

Doc/whatsnew/3.12.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ Inlining does result in a few visible behavior changes:
253253
* Calling :func:`locals` inside a comprehension now includes variables
254254
from outside the comprehension, and no longer includes the synthetic ``.0``
255255
variable for the comprehension "argument".
256+
* A comprehension iterating directly over ``locals()`` (e.g. ``[k for k in
257+
locals()]``) may see "RuntimeError: dictionary changed size during iteration"
258+
when run under tracing (e.g. code coverage measurement). This is the same
259+
behavior already seen in e.g. ``for k in locals():``. To avoid the error, first
260+
create a list of keys to iterate over: ``keys = list(locals()); [k for k in
261+
keys]``.
256262

257263
Contributed by Carl Meyer and Vladimir Matveev in :pep:`709`.
258264

Include/internal/pycore_ceval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ extern PyObject* _Py_MakeCoro(PyFunctionObject *func);
156156
and asynchronous exception */
157157
extern int _Py_HandlePending(PyThreadState *tstate);
158158

159+
extern PyObject * _PyEval_GetFrameLocals(void);
159160

160161

161162
#ifdef __cplusplus

Include/internal/pycore_frame.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame * frame);
234234
int
235235
_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg);
236236

237+
PyObject *
238+
_PyFrame_GetLocals(_PyInterpreterFrame *frame, int include_hidden);
239+
237240
int
238241
_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame);
239242

Lib/functools.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -957,9 +957,10 @@ def __isabstractmethod__(self):
957957

958958

959959
################################################################################
960-
### cached_property() - computed once per instance, cached as attribute
960+
### cached_property() - property result cached as instance attribute
961961
################################################################################
962962

963+
_NOT_FOUND = object()
963964

964965
class cached_property:
965966
def __init__(self, func):
@@ -990,15 +991,17 @@ def __get__(self, instance, owner=None):
990991
f"instance to cache {self.attrname!r} property."
991992
)
992993
raise TypeError(msg) from None
993-
val = self.func(instance)
994-
try:
995-
cache[self.attrname] = val
996-
except TypeError:
997-
msg = (
998-
f"The '__dict__' attribute on {type(instance).__name__!r} instance "
999-
f"does not support item assignment for caching {self.attrname!r} property."
1000-
)
1001-
raise TypeError(msg) from None
994+
val = cache.get(self.attrname, _NOT_FOUND)
995+
if val is _NOT_FOUND:
996+
val = self.func(instance)
997+
try:
998+
cache[self.attrname] = val
999+
except TypeError:
1000+
msg = (
1001+
f"The '__dict__' attribute on {type(instance).__name__!r} instance "
1002+
f"does not support item assignment for caching {self.attrname!r} property."
1003+
)
1004+
raise TypeError(msg) from None
10021005
return val
10031006

10041007
__class_getitem__ = classmethod(GenericAlias)

Lib/logging/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,11 @@ def _acquireLock():
238238
This should be released with _releaseLock().
239239
"""
240240
if _lock:
241-
_lock.acquire()
241+
try:
242+
_lock.acquire()
243+
except BaseException:
244+
_lock.release()
245+
raise
242246

243247
def _releaseLock():
244248
"""

Lib/test/test_functools.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3037,6 +3037,25 @@ def test_access_from_class(self):
30373037
def test_doc(self):
30383038
self.assertEqual(CachedCostItem.cost.__doc__, "The cost of the item.")
30393039

3040+
def test_subclass_with___set__(self):
3041+
"""Caching still works for a subclass defining __set__."""
3042+
class readonly_cached_property(py_functools.cached_property):
3043+
def __set__(self, obj, value):
3044+
raise AttributeError("read only property")
3045+
3046+
class Test:
3047+
def __init__(self, prop):
3048+
self._prop = prop
3049+
3050+
@readonly_cached_property
3051+
def prop(self):
3052+
return self._prop
3053+
3054+
t = Test(1)
3055+
self.assertEqual(t.prop, 1)
3056+
t._prop = 999
3057+
self.assertEqual(t.prop, 1)
3058+
30403059

30413060
if __name__ == '__main__':
30423061
unittest.main()

0 commit comments

Comments
 (0)
0