Skip to content

Commit 91220ad

Browse files
committed
Merge branch 'main' into gh-117474-gdb-gil
2 parents 3aa402a + 4220514 commit 91220ad

File tree

177 files changed

+7862
-5248
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

177 files changed

+7862
-5248
lines changed

Doc/howto/logging-cookbook.rst

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,14 +1915,15 @@ In a similar way to the above section, we can implement a listener and handler
19151915
using `pynng <https://pypi.org/project/pynng/>`_, which is a Python binding to
19161916
`NNG <https://nng.nanomsg.org/>`_, billed as a spiritual successor to ZeroMQ.
19171917
The following snippets illustrate -- you can test them in an environment which has
1918-
``pynng`` installed. Juat for variety, we present the listener first.
1918+
``pynng`` installed. Just for variety, we present the listener first.
19191919

19201920

19211921
Subclass ``QueueListener``
19221922
^^^^^^^^^^^^^^^^^^^^^^^^^^
19231923

19241924
.. code-block:: python
19251925
1926+
# listener.py
19261927
import json
19271928
import logging
19281929
import logging.handlers
@@ -1955,7 +1956,7 @@ Subclass ``QueueListener``
19551956
break
19561957
except pynng.Timeout:
19571958
pass
1958-
except pynng.Closed: # sometimes hit when you hit Ctrl-C
1959+
except pynng.Closed: # sometimes happens when you hit Ctrl-C
19591960
break
19601961
if data is None:
19611962
return None
@@ -1988,6 +1989,7 @@ Subclass ``QueueHandler``
19881989

19891990
.. code-block:: python
19901991
1992+
# sender.py
19911993
import json
19921994
import logging
19931995
import logging.handlers
@@ -2015,9 +2017,10 @@ Subclass ``QueueHandler``
20152017
20162018
logging.getLogger('pynng').propagate = False
20172019
handler = NNGSocketHandler(DEFAULT_ADDR)
2020+
# Make sure the process ID is in the output
20182021
logging.basicConfig(level=logging.DEBUG,
20192022
handlers=[logging.StreamHandler(), handler],
2020-
format='%(levelname)-8s %(name)10s %(message)s')
2023+
format='%(levelname)-8s %(name)10s %(process)6s %(message)s')
20212024
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
20222025
logging.CRITICAL)
20232026
logger_names = ('myapp', 'myapp.lib1', 'myapp.lib2')
@@ -2031,7 +2034,64 @@ Subclass ``QueueHandler``
20312034
delay = random.random() * 2 + 0.5
20322035
time.sleep(delay)
20332036
2034-
You can run the above two snippets in separate command shells.
2037+
You can run the above two snippets in separate command shells. If we run the
2038+
listener in one shell and run the sender in two separate shells, we should see
2039+
something like the following. In the first sender shell:
2040+
2041+
.. code-block:: console
2042+
2043+
$ python sender.py
2044+
DEBUG myapp 613 Message no. 1
2045+
WARNING myapp.lib2 613 Message no. 2
2046+
CRITICAL myapp.lib2 613 Message no. 3
2047+
WARNING myapp.lib2 613 Message no. 4
2048+
CRITICAL myapp.lib1 613 Message no. 5
2049+
DEBUG myapp 613 Message no. 6
2050+
CRITICAL myapp.lib1 613 Message no. 7
2051+
INFO myapp.lib1 613 Message no. 8
2052+
(and so on)
2053+
2054+
In the second sender shell:
2055+
2056+
.. code-block:: console
2057+
2058+
$ python sender.py
2059+
INFO myapp.lib2 657 Message no. 1
2060+
CRITICAL myapp.lib2 657 Message no. 2
2061+
CRITICAL myapp 657 Message no. 3
2062+
CRITICAL myapp.lib1 657 Message no. 4
2063+
INFO myapp.lib1 657 Message no. 5
2064+
WARNING myapp.lib2 657 Message no. 6
2065+
CRITICAL myapp 657 Message no. 7
2066+
DEBUG myapp.lib1 657 Message no. 8
2067+
(and so on)
2068+
2069+
In the listener shell:
2070+
2071+
.. code-block:: console
2072+
2073+
$ python listener.py
2074+
Press Ctrl-C to stop.
2075+
DEBUG myapp 613 Message no. 1
2076+
WARNING myapp.lib2 613 Message no. 2
2077+
INFO myapp.lib2 657 Message no. 1
2078+
CRITICAL myapp.lib2 613 Message no. 3
2079+
CRITICAL myapp.lib2 657 Message no. 2
2080+
CRITICAL myapp 657 Message no. 3
2081+
WARNING myapp.lib2 613 Message no. 4
2082+
CRITICAL myapp.lib1 613 Message no. 5
2083+
CRITICAL myapp.lib1 657 Message no. 4
2084+
INFO myapp.lib1 657 Message no. 5
2085+
DEBUG myapp 613 Message no. 6
2086+
WARNING myapp.lib2 657 Message no. 6
2087+
CRITICAL myapp 657 Message no. 7
2088+
CRITICAL myapp.lib1 613 Message no. 7
2089+
INFO myapp.lib1 613 Message no. 8
2090+
DEBUG myapp.lib1 657 Message no. 8
2091+
(and so on)
2092+
2093+
As you can see, the logging from the two sender processes is interleaved in the
2094+
listener's output.
20352095

20362096

20372097
An example dictionary-based configuration

Doc/library/datetime.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,24 @@ Other constructors, all class methods:
10791079
time tuple. See also :ref:`strftime-strptime-behavior` and
10801080
:meth:`datetime.fromisoformat`.
10811081

1082+
.. versionchanged:: 3.13
1083+
1084+
If *format* specifies a day of month without a year a
1085+
:exc:`DeprecationWarning` is now emitted. This is to avoid a quadrennial
1086+
leap year bug in code seeking to parse only a month and day as the
1087+
default year used in absence of one in the format is not a leap year.
1088+
Such *format* values may raise an error as of Python 3.15. The
1089+
workaround is to always include a year in your *format*. If parsing
1090+
*date_string* values that do not have a year, explicitly add a year that
1091+
is a leap year before parsing:
1092+
1093+
.. doctest::
1094+
1095+
>>> from datetime import datetime
1096+
>>> date_string = "02/29"
1097+
>>> when = datetime.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug.
1098+
>>> when.strftime("%B %d") # doctest: +SKIP
1099+
'February 29'
10821100

10831101

10841102
Class attributes:
@@ -2657,6 +2675,25 @@ Notes:
26572675
for formats ``%d``, ``%m``, ``%H``, ``%I``, ``%M``, ``%S``, ``%j``, ``%U``,
26582676
``%W``, and ``%V``. Format ``%y`` does require a leading zero.
26592677

2678+
(10)
2679+
When parsing a month and day using :meth:`~.datetime.strptime`, always
2680+
include a year in the format. If the value you need to parse lacks a year,
2681+
append an explicit dummy leap year. Otherwise your code will raise an
2682+
exception when it encounters leap day because the default year used by the
2683+
parser is not a leap year. Users run into this bug every four years...
2684+
2685+
.. doctest::
2686+
2687+
>>> month_day = "02/29"
2688+
>>> datetime.strptime(f"{month_day};1984", "%m/%d;%Y") # No leap year bug.
2689+
datetime.datetime(1984, 2, 29, 0, 0)
2690+
2691+
.. deprecated-removed:: 3.13 3.15
2692+
:meth:`~.datetime.strptime` calls using a format string containing
2693+
a day of month without a year now emit a
2694+
:exc:`DeprecationWarning`. In 3.15 or later we may change this into
2695+
an error or change the default year to a leap year. See :gh:`70647`.
2696+
26602697
.. rubric:: Footnotes
26612698

26622699
.. [#] If, that is, we ignore the effects of Relativity

Doc/library/logging.rst

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ If you run *myapp.py*, you should see this in *myapp.log*:
6363
INFO:mylib:Doing something
6464
INFO:__main__:Finished
6565
66-
The key features of this idiomatic usage is that the majority of code is simply
66+
The key feature of this idiomatic usage is that the majority of code is simply
6767
creating a module level logger with ``getLogger(__name__)``, and using that
68-
logger to do any needed logging. This is concise while allowing downstream code
69-
fine grained control if needed. Logged messages to the module-level logger get
70-
forwarded up to handlers of loggers in higher-level modules, all the way up to
71-
the root logger; for this reason this approach is known as hierarchical logging.
68+
logger to do any needed logging. This is concise, while allowing downstream
69+
code fine-grained control if needed. Logged messages to the module-level logger
70+
get forwarded to handlers of loggers in higher-level modules, all the way up to
71+
the highest-level logger known as the root logger; this approach is known as
72+
hierarchical logging.
7273

7374
For logging to be useful, it needs to be configured: setting the levels and
7475
destinations for each logger, potentially changing how specific modules log,
@@ -82,8 +83,8 @@ The module provides a lot of functionality and flexibility. If you are
8283
unfamiliar with logging, the best way to get to grips with it is to view the
8384
tutorials (**see the links above and on the right**).
8485

85-
The basic classes defined by the module, together with their functions, are
86-
listed below.
86+
The basic classes defined by the module, together with their attributes and
87+
methods, are listed in the sections below.
8788

8889
* Loggers expose the interface that application code directly uses.
8990
* Handlers send the log records (created by loggers) to the appropriate

Doc/library/test.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,12 @@ The :mod:`test.support` module defines the following functions:
731731
macOS version is less than the minimum, the test is skipped.
732732

733733

734+
.. decorator:: requires_gil_enabled
735+
736+
Decorator for skipping tests on the free-threaded build. If the
737+
:term:`GIL` is disabled, the test is skipped.
738+
739+
734740
.. decorator:: requires_IEEE_754
735741

736742
Decorator for skipping tests on non-IEEE 754 platforms.

Doc/library/unittest.rst

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,8 +1880,8 @@ Loading and running tests
18801880
Python identifiers) will be loaded.
18811881

18821882
All test modules must be importable from the top level of the project. If
1883-
the start directory is not the top level directory then the top level
1884-
directory must be specified separately.
1883+
the start directory is not the top level directory then *top_level_dir*
1884+
must be specified separately.
18851885

18861886
If importing a module fails, for example due to a syntax error, then
18871887
this will be recorded as a single error and discovery will continue. If
@@ -1901,9 +1901,11 @@ Loading and running tests
19011901
package.
19021902

19031903
The pattern is deliberately not stored as a loader attribute so that
1904-
packages can continue discovery themselves. *top_level_dir* is stored so
1905-
``load_tests`` does not need to pass this argument in to
1906-
``loader.discover()``.
1904+
packages can continue discovery themselves.
1905+
1906+
*top_level_dir* is stored internally, and used as a default to any
1907+
nested calls to ``discover()``. That is, if a package's ``load_tests``
1908+
calls ``loader.discover()``, it does not need to pass this argument.
19071909

19081910
*start_dir* can be a dotted module name as well as a directory.
19091911

@@ -1930,6 +1932,9 @@ Loading and running tests
19301932
*start_dir* can not be a :term:`namespace packages <namespace package>`.
19311933
It has been broken since Python 3.7 and Python 3.11 officially remove it.
19321934

1935+
.. versionchanged:: 3.13
1936+
*top_level_dir* is only stored for the duration of *discover* call.
1937+
19331938

19341939
The following attributes of a :class:`TestLoader` can be configured either by
19351940
subclassing or assignment on an instance:

Include/cpython/code.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ typedef struct _Py_GlobalMonitors {
2424
uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS];
2525
} _Py_GlobalMonitors;
2626

27+
typedef struct {
28+
union {
29+
struct {
30+
uint16_t backoff : 4;
31+
uint16_t value : 12;
32+
};
33+
uint16_t as_counter; // For printf("%#x", ...)
34+
};
35+
} _Py_BackoffCounter;
36+
2737
/* Each instruction in a code object is a fixed-width value,
2838
* currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG
2939
* opcode allows for larger values but the current limit is 3 uses
@@ -39,6 +49,7 @@ typedef union {
3949
uint8_t code;
4050
uint8_t arg;
4151
} op;
52+
_Py_BackoffCounter counter; // First cache entry of specializable op
4253
} _Py_CODEUNIT;
4354

4455

Include/cpython/optimizer.h

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
8989

9090
typedef struct _exit_data {
9191
uint32_t target;
92-
int16_t temperature;
92+
_Py_BackoffCounter temperature;
9393
const struct _PyExecutorObject *executor;
9494
} _PyExitData;
9595

@@ -115,11 +115,6 @@ typedef int (*optimize_func)(
115115
struct _PyOptimizerObject {
116116
PyObject_HEAD
117117
optimize_func optimize;
118-
/* These thresholds are treated as signed so do not exceed INT16_MAX
119-
* Use INT16_MAX to indicate that the optimizer should never be called */
120-
uint16_t resume_threshold;
121-
uint16_t side_threshold;
122-
uint16_t backedge_threshold;
123118
/* Data needed by the optimizer goes here, but is opaque to the VM */
124119
};
125120

@@ -151,14 +146,6 @@ extern void _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_inval
151146
PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void);
152147
PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewUOpOptimizer(void);
153148

154-
#define OPTIMIZER_BITS_IN_COUNTER 4
155-
/* Minimum of 16 additional executions before retry */
156-
#define MIN_TIER2_BACKOFF 4
157-
#define MAX_TIER2_BACKOFF (15 - OPTIMIZER_BITS_IN_COUNTER)
158-
#define OPTIMIZER_BITS_MASK ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1)
159-
/* A value <= UINT16_MAX but large enough that when shifted is > UINT16_MAX */
160-
#define OPTIMIZER_UNREACHABLE_THRESHOLD UINT16_MAX
161-
162149
#define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3
163150
#define _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS 6
164151

0 commit comments

Comments
 (0)