Skip to content

Commit 6179c2f

Browse files
committed
Merge remote-tracking branch 'cpython/main' into pythongh-89545
2 parents 1264330 + 88671a9 commit 6179c2f

File tree

13 files changed

+146
-19
lines changed

13 files changed

+146
-19
lines changed

.github/workflows/project-updater.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@ on:
88

99
jobs:
1010
add-to-project:
11-
name: Add to the Release and Deferred Blocker project
11+
name: Add issues to projects
1212
runs-on: ubuntu-latest
13+
strategy:
14+
matrix:
15+
include:
16+
# if an issue has any of these labels, it will be added
17+
# to the corresponding project
18+
- { project: 2, label: "release-blocker, deferred-blocker" }
19+
- { project: 3, label: expert-subinterpreters }
20+
- { project: 29, label: expert-asyncio }
21+
1322
steps:
1423
- uses: actions/[email protected]
1524
with:
16-
project-url: https://github.com/orgs/python/projects/2
25+
project-url: https://github.com/orgs/python/projects/${{ matrix.project }}
1726
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
18-
labeled: release-blocker, deferred-blocker
19-
label-operator: OR
27+
labeled: ${{ matrix.label }}

Doc/howto/perf_profiling.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ active since the start of the Python interpreter, you can use the `-Xperf` optio
155155

156156
$ python -Xperf my_script.py
157157

158+
You can also set the :envvar:`PYTHONPERFSUPPORT` to a nonzero value to actiavate perf
159+
profiling mode globally.
160+
158161
There is also support for dynamically activating and deactivating the perf
159162
profiling mode by using the APIs in the :mod:`sys` module:
160163

Doc/library/http.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,31 @@ equal to the constant name (i.e. ``http.HTTPStatus.OK`` is also available as
137137
.. versionadded:: 3.9
138138
Added ``103 EARLY_HINTS``, ``418 IM_A_TEAPOT`` and ``425 TOO_EARLY`` status codes.
139139

140+
HTTP status category
141+
--------------------
142+
143+
.. versionadded:: 3.11
144+
145+
The enum values have several properties to indicate the HTTP status category:
146+
147+
==================== ======================== ===============================
148+
Property Indicates that Details
149+
==================== ======================== ===============================
150+
``is_informational`` ``100 <= status <= 199`` HTTP/1.1 :rfc:`7231`, Section 6
151+
``is_success`` ``200 <= status <= 299`` HTTP/1.1 :rfc:`7231`, Section 6
152+
``is_redirection`` ``300 <= status <= 399`` HTTP/1.1 :rfc:`7231`, Section 6
153+
``is_client_error`` ``400 <= status <= 499`` HTTP/1.1 :rfc:`7231`, Section 6
154+
``is_server_error`` ``500 <= status <= 599`` HTTP/1.1 :rfc:`7231`, Section 6
155+
==================== ======================== ===============================
156+
157+
Usage::
158+
159+
>>> from http import HTTPStatus
160+
>>> HTTPStatus.OK.is_success
161+
True
162+
>>> HTTPStatus.OK.is_client_error
163+
False
164+
140165
.. class:: HTTPMethod
141166

142167
.. versionadded:: 3.11

Doc/library/sqlite3.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,8 +1653,8 @@ How-to guides
16531653

16541654
.. _sqlite3-placeholders:
16551655

1656-
Using placeholders to bind values in SQL queries
1657-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1656+
How to use placeholders to bind values in SQL queries
1657+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16581658

16591659
SQL operations usually need to use values from Python variables. However,
16601660
beware of using Python's string operations to assemble queries, as they

Doc/using/cmdline.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ Miscellaneous options
582582
.. versionadded:: 3.11
583583
The ``-X frozen_modules`` option.
584584

585+
.. versionadded:: 3.12
586+
The ``-X perf`` option.
585587

586588

587589
Options you shouldn't use

Lib/enum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1887,7 +1887,7 @@ def _test_simple_enum(checked_enum, simple_enum):
18871887
else:
18881888
checked_value = checked_dict[key]
18891889
simple_value = simple_dict[key]
1890-
if callable(checked_value):
1890+
if callable(checked_value) or isinstance(checked_value, bltns.property):
18911891
continue
18921892
if key == '__doc__':
18931893
# remove all spaces/tabs

Lib/http/__init__.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ def __new__(cls, value, phrase, description=''):
3131
obj.description = description
3232
return obj
3333

34+
@property
35+
def is_informational(self):
36+
return 100 <= self <= 199
37+
38+
@property
39+
def is_success(self):
40+
return 200 <= self <= 299
41+
42+
@property
43+
def is_redirection(self):
44+
return 300 <= self <= 399
45+
46+
@property
47+
def is_client_error(self):
48+
return 400 <= self <= 499
49+
50+
@property
51+
def is_server_error(self):
52+
return 500 <= self <= 599
53+
3454
# informational
3555
CONTINUE = 100, 'Continue', 'Request received, please continue'
3656
SWITCHING_PROTOCOLS = (101, 'Switching Protocols',

Lib/test/test_dictviews.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ def test_items_set_operations(self):
170170
{('a', 1), ('b', 2)})
171171
self.assertEqual(d1.items() & set(d2.items()), {('b', 2)})
172172
self.assertEqual(d1.items() & set(d3.items()), set())
173+
self.assertEqual(d1.items() & (("a", 1), ("b", 2)),
174+
{('a', 1), ('b', 2)})
175+
self.assertEqual(d1.items() & (("a", 2), ("b", 2)), {('b', 2)})
176+
self.assertEqual(d1.items() & (("d", 4), ("e", 5)), set())
173177

174178
self.assertEqual(d1.items() | d1.items(),
175179
{('a', 1), ('b', 2)})
@@ -183,19 +187,33 @@ def test_items_set_operations(self):
183187
{('a', 1), ('a', 2), ('b', 2)})
184188
self.assertEqual(d1.items() | set(d3.items()),
185189
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})
190+
self.assertEqual(d1.items() | (('a', 1), ('b', 2)),
191+
{('a', 1), ('b', 2)})
192+
self.assertEqual(d1.items() | (('a', 2), ('b', 2)),
193+
{('a', 1), ('a', 2), ('b', 2)})
194+
self.assertEqual(d1.items() | (('d', 4), ('e', 5)),
195+
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})
186196

187197
self.assertEqual(d1.items() ^ d1.items(), set())
188198
self.assertEqual(d1.items() ^ d2.items(),
189199
{('a', 1), ('a', 2)})
190200
self.assertEqual(d1.items() ^ d3.items(),
191201
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})
202+
self.assertEqual(d1.items() ^ (('a', 1), ('b', 2)), set())
203+
self.assertEqual(d1.items() ^ (("a", 2), ("b", 2)),
204+
{('a', 1), ('a', 2)})
205+
self.assertEqual(d1.items() ^ (("d", 4), ("e", 5)),
206+
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})
192207

193208
self.assertEqual(d1.items() - d1.items(), set())
194209
self.assertEqual(d1.items() - d2.items(), {('a', 1)})
195210
self.assertEqual(d1.items() - d3.items(), {('a', 1), ('b', 2)})
196211
self.assertEqual(d1.items() - set(d1.items()), set())
197212
self.assertEqual(d1.items() - set(d2.items()), {('a', 1)})
198213
self.assertEqual(d1.items() - set(d3.items()), {('a', 1), ('b', 2)})
214+
self.assertEqual(d1.items() - (('a', 1), ('b', 2)), set())
215+
self.assertEqual(d1.items() - (("a", 2), ("b", 2)), {('a', 1)})
216+
self.assertEqual(d1.items() - (("d", 4), ("e", 5)), {('a', 1), ('b', 2)})
199217

200218
self.assertFalse(d1.items().isdisjoint(d1.items()))
201219
self.assertFalse(d1.items().isdisjoint(d2.items()))

Lib/test/test_httplib.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,27 @@ def __new__(cls, value, phrase, description=''):
553553
obj.phrase = phrase
554554
obj.description = description
555555
return obj
556+
557+
@property
558+
def is_informational(self):
559+
return 100 <= self <= 199
560+
561+
@property
562+
def is_success(self):
563+
return 200 <= self <= 299
564+
565+
@property
566+
def is_redirection(self):
567+
return 300 <= self <= 399
568+
569+
@property
570+
def is_client_error(self):
571+
return 400 <= self <= 499
572+
573+
@property
574+
def is_server_error(self):
575+
return 500 <= self <= 599
576+
556577
# informational
557578
CONTINUE = 100, 'Continue', 'Request received, please continue'
558579
SWITCHING_PROTOCOLS = (101, 'Switching Protocols',
@@ -669,6 +690,30 @@ def __new__(cls, value, phrase, description=''):
669690
'The client needs to authenticate to gain network access')
670691
enum._test_simple_enum(CheckedHTTPStatus, HTTPStatus)
671692

693+
def test_httpstatus_range(self):
694+
"""Checks that the statuses are in the 100-599 range"""
695+
696+
for member in HTTPStatus.__members__.values():
697+
self.assertGreaterEqual(member, 100)
698+
self.assertLessEqual(member, 599)
699+
700+
def test_httpstatus_category(self):
701+
"""Checks that the statuses belong to the standard categories"""
702+
703+
categories = (
704+
((100, 199), "is_informational"),
705+
((200, 299), "is_success"),
706+
((300, 399), "is_redirection"),
707+
((400, 499), "is_client_error"),
708+
((500, 599), "is_server_error"),
709+
)
710+
for member in HTTPStatus.__members__.values():
711+
for (lower, upper), category in categories:
712+
category_indicator = getattr(member, category)
713+
if lower <= member <= upper:
714+
self.assertTrue(category_indicator)
715+
else:
716+
self.assertFalse(category_indicator)
672717

673718
def test_status_lines(self):
674719
# Test HTTP status lines

Lib/test/test_perf_profiler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def baz():
5858
script = make_script(script_dir, "perftest", code)
5959
with subprocess.Popen(
6060
[sys.executable, "-Xperf", script],
61-
universal_newlines=True,
61+
text=True,
6262
stderr=subprocess.PIPE,
6363
stdout=subprocess.PIPE,
6464
) as process:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :class:`HTTPStatus <http.HTTPStatus>` enum offers a couple of properties
2+
to indicate the HTTP status category e.g. ``HTTPStatus.OK.is_success``.

Objects/perf_trampoline.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,12 +284,23 @@ new_code_arena(void)
284284
void *start = &_Py_trampoline_func_start;
285285
void *end = &_Py_trampoline_func_end;
286286
size_t code_size = end - start;
287+
// TODO: Check the effect of alignment of the code chunks. Initial investigation
288+
// showed that this has no effect on performance in x86-64 or aarch64 and the current
289+
// version has the advantage that the unwinder in GDB can unwind across JIT-ed code.
290+
//
291+
// We should check the values in the future and see if there is a
292+
// measurable performance improvement by rounding trampolines up to 32-bit
293+
// or 64-bit alignment.
287294

288295
size_t n_copies = mem_size / code_size;
289296
for (size_t i = 0; i < n_copies; i++) {
290297
memcpy(memory + i * code_size, start, code_size * sizeof(char));
291298
}
292299
// Some systems may prevent us from creating executable code on the fly.
300+
// TODO: Call icache invalidation intrinsics if available:
301+
// __builtin___clear_cache/__clear_cache (depending if clang/gcc). This is
302+
// technically not necessary but we could be missing something so better be
303+
// safe.
293304
int res = mprotect(memory, mem_size, PROT_READ | PROT_EXEC);
294305
if (res == -1) {
295306
PyErr_SetFromErrno(PyExc_OSError);

Python/ceval.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
16211621
PyObject *sub = TOP();
16221622
PyObject *res = PyDict_GetItemWithError(dict, sub);
16231623
if (res == NULL) {
1624-
goto binary_subscr_dict_error;
1624+
if (!_PyErr_Occurred(tstate)) {
1625+
_PyErr_SetKeyError(sub);
1626+
}
1627+
goto error;
16251628
}
16261629
Py_INCREF(res);
16271630
STACK_SHRINK(1);
@@ -5193,16 +5196,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
51935196
DISPATCH_GOTO();
51945197
}
51955198

5196-
binary_subscr_dict_error:
5197-
{
5198-
PyObject *sub = POP();
5199-
if (!_PyErr_Occurred(tstate)) {
5200-
_PyErr_SetKeyError(sub);
5201-
}
5202-
Py_DECREF(sub);
5203-
goto error;
5204-
}
5205-
52065199
unbound_local_error:
52075200
{
52085201
format_exc_check_arg(tstate, PyExc_UnboundLocalError,

0 commit comments

Comments
 (0)