Skip to content

Commit

Permalink
Merge remote-tracking branch 'cpython/main' into pythongh-89545
Browse files Browse the repository at this point in the history
  • Loading branch information
zooba committed Aug 30, 2022
2 parents 1264330 + 88671a9 commit 6179c2f
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 19 deletions.
16 changes: 12 additions & 4 deletions .github/workflows/project-updater.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@ on:

jobs:
add-to-project:
name: Add to the Release and Deferred Blocker project
name: Add issues to projects
runs-on: ubuntu-latest
strategy:
matrix:
include:
# if an issue has any of these labels, it will be added
# to the corresponding project
- { project: 2, label: "release-blocker, deferred-blocker" }
- { project: 3, label: expert-subinterpreters }
- { project: 29, label: expert-asyncio }

steps:
- uses: actions/add-to-project@v0.1.0
with:
project-url: https://github.com/orgs/python/projects/2
project-url: https://github.com/orgs/python/projects/${{ matrix.project }}
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
labeled: release-blocker, deferred-blocker
label-operator: OR
labeled: ${{ matrix.label }}
3 changes: 3 additions & 0 deletions Doc/howto/perf_profiling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ active since the start of the Python interpreter, you can use the `-Xperf` optio

$ python -Xperf my_script.py

You can also set the :envvar:`PYTHONPERFSUPPORT` to a nonzero value to actiavate perf
profiling mode globally.

There is also support for dynamically activating and deactivating the perf
profiling mode by using the APIs in the :mod:`sys` module:

Expand Down
25 changes: 25 additions & 0 deletions Doc/library/http.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,31 @@ equal to the constant name (i.e. ``http.HTTPStatus.OK`` is also available as
.. versionadded:: 3.9
Added ``103 EARLY_HINTS``, ``418 IM_A_TEAPOT`` and ``425 TOO_EARLY`` status codes.

HTTP status category
--------------------

.. versionadded:: 3.11

The enum values have several properties to indicate the HTTP status category:

==================== ======================== ===============================
Property Indicates that Details
==================== ======================== ===============================
``is_informational`` ``100 <= status <= 199`` HTTP/1.1 :rfc:`7231`, Section 6
``is_success`` ``200 <= status <= 299`` HTTP/1.1 :rfc:`7231`, Section 6
``is_redirection`` ``300 <= status <= 399`` HTTP/1.1 :rfc:`7231`, Section 6
``is_client_error`` ``400 <= status <= 499`` HTTP/1.1 :rfc:`7231`, Section 6
``is_server_error`` ``500 <= status <= 599`` HTTP/1.1 :rfc:`7231`, Section 6
==================== ======================== ===============================

Usage::

>>> from http import HTTPStatus
>>> HTTPStatus.OK.is_success
True
>>> HTTPStatus.OK.is_client_error
False

.. class:: HTTPMethod

.. versionadded:: 3.11
Expand Down
4 changes: 2 additions & 2 deletions Doc/library/sqlite3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1653,8 +1653,8 @@ How-to guides

.. _sqlite3-placeholders:

Using placeholders to bind values in SQL queries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How to use placeholders to bind values in SQL queries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

SQL operations usually need to use values from Python variables. However,
beware of using Python's string operations to assemble queries, as they
Expand Down
2 changes: 2 additions & 0 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ Miscellaneous options
.. versionadded:: 3.11
The ``-X frozen_modules`` option.

.. versionadded:: 3.12
The ``-X perf`` option.


Options you shouldn't use
Expand Down
2 changes: 1 addition & 1 deletion Lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -1887,7 +1887,7 @@ def _test_simple_enum(checked_enum, simple_enum):
else:
checked_value = checked_dict[key]
simple_value = simple_dict[key]
if callable(checked_value):
if callable(checked_value) or isinstance(checked_value, bltns.property):
continue
if key == '__doc__':
# remove all spaces/tabs
Expand Down
20 changes: 20 additions & 0 deletions Lib/http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ def __new__(cls, value, phrase, description=''):
obj.description = description
return obj

@property
def is_informational(self):
return 100 <= self <= 199

@property
def is_success(self):
return 200 <= self <= 299

@property
def is_redirection(self):
return 300 <= self <= 399

@property
def is_client_error(self):
return 400 <= self <= 499

@property
def is_server_error(self):
return 500 <= self <= 599

# informational
CONTINUE = 100, 'Continue', 'Request received, please continue'
SWITCHING_PROTOCOLS = (101, 'Switching Protocols',
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/test_dictviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ def test_items_set_operations(self):
{('a', 1), ('b', 2)})
self.assertEqual(d1.items() & set(d2.items()), {('b', 2)})
self.assertEqual(d1.items() & set(d3.items()), set())
self.assertEqual(d1.items() & (("a", 1), ("b", 2)),
{('a', 1), ('b', 2)})
self.assertEqual(d1.items() & (("a", 2), ("b", 2)), {('b', 2)})
self.assertEqual(d1.items() & (("d", 4), ("e", 5)), set())

self.assertEqual(d1.items() | d1.items(),
{('a', 1), ('b', 2)})
Expand All @@ -183,19 +187,33 @@ def test_items_set_operations(self):
{('a', 1), ('a', 2), ('b', 2)})
self.assertEqual(d1.items() | set(d3.items()),
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})
self.assertEqual(d1.items() | (('a', 1), ('b', 2)),
{('a', 1), ('b', 2)})
self.assertEqual(d1.items() | (('a', 2), ('b', 2)),
{('a', 1), ('a', 2), ('b', 2)})
self.assertEqual(d1.items() | (('d', 4), ('e', 5)),
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})

self.assertEqual(d1.items() ^ d1.items(), set())
self.assertEqual(d1.items() ^ d2.items(),
{('a', 1), ('a', 2)})
self.assertEqual(d1.items() ^ d3.items(),
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})
self.assertEqual(d1.items() ^ (('a', 1), ('b', 2)), set())
self.assertEqual(d1.items() ^ (("a", 2), ("b", 2)),
{('a', 1), ('a', 2)})
self.assertEqual(d1.items() ^ (("d", 4), ("e", 5)),
{('a', 1), ('b', 2), ('d', 4), ('e', 5)})

self.assertEqual(d1.items() - d1.items(), set())
self.assertEqual(d1.items() - d2.items(), {('a', 1)})
self.assertEqual(d1.items() - d3.items(), {('a', 1), ('b', 2)})
self.assertEqual(d1.items() - set(d1.items()), set())
self.assertEqual(d1.items() - set(d2.items()), {('a', 1)})
self.assertEqual(d1.items() - set(d3.items()), {('a', 1), ('b', 2)})
self.assertEqual(d1.items() - (('a', 1), ('b', 2)), set())
self.assertEqual(d1.items() - (("a", 2), ("b", 2)), {('a', 1)})
self.assertEqual(d1.items() - (("d", 4), ("e", 5)), {('a', 1), ('b', 2)})

self.assertFalse(d1.items().isdisjoint(d1.items()))
self.assertFalse(d1.items().isdisjoint(d2.items()))
Expand Down
45 changes: 45 additions & 0 deletions Lib/test/test_httplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,27 @@ def __new__(cls, value, phrase, description=''):
obj.phrase = phrase
obj.description = description
return obj

@property
def is_informational(self):
return 100 <= self <= 199

@property
def is_success(self):
return 200 <= self <= 299

@property
def is_redirection(self):
return 300 <= self <= 399

@property
def is_client_error(self):
return 400 <= self <= 499

@property
def is_server_error(self):
return 500 <= self <= 599

# informational
CONTINUE = 100, 'Continue', 'Request received, please continue'
SWITCHING_PROTOCOLS = (101, 'Switching Protocols',
Expand Down Expand Up @@ -669,6 +690,30 @@ def __new__(cls, value, phrase, description=''):
'The client needs to authenticate to gain network access')
enum._test_simple_enum(CheckedHTTPStatus, HTTPStatus)

def test_httpstatus_range(self):
"""Checks that the statuses are in the 100-599 range"""

for member in HTTPStatus.__members__.values():
self.assertGreaterEqual(member, 100)
self.assertLessEqual(member, 599)

def test_httpstatus_category(self):
"""Checks that the statuses belong to the standard categories"""

categories = (
((100, 199), "is_informational"),
((200, 299), "is_success"),
((300, 399), "is_redirection"),
((400, 499), "is_client_error"),
((500, 599), "is_server_error"),
)
for member in HTTPStatus.__members__.values():
for (lower, upper), category in categories:
category_indicator = getattr(member, category)
if lower <= member <= upper:
self.assertTrue(category_indicator)
else:
self.assertFalse(category_indicator)

def test_status_lines(self):
# Test HTTP status lines
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_perf_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def baz():
script = make_script(script_dir, "perftest", code)
with subprocess.Popen(
[sys.executable, "-Xperf", script],
universal_newlines=True,
text=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
) as process:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The :class:`HTTPStatus <http.HTTPStatus>` enum offers a couple of properties
to indicate the HTTP status category e.g. ``HTTPStatus.OK.is_success``.
11 changes: 11 additions & 0 deletions Objects/perf_trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,23 @@ new_code_arena(void)
void *start = &_Py_trampoline_func_start;
void *end = &_Py_trampoline_func_end;
size_t code_size = end - start;
// TODO: Check the effect of alignment of the code chunks. Initial investigation
// showed that this has no effect on performance in x86-64 or aarch64 and the current
// version has the advantage that the unwinder in GDB can unwind across JIT-ed code.
//
// We should check the values in the future and see if there is a
// measurable performance improvement by rounding trampolines up to 32-bit
// or 64-bit alignment.

size_t n_copies = mem_size / code_size;
for (size_t i = 0; i < n_copies; i++) {
memcpy(memory + i * code_size, start, code_size * sizeof(char));
}
// Some systems may prevent us from creating executable code on the fly.
// TODO: Call icache invalidation intrinsics if available:
// __builtin___clear_cache/__clear_cache (depending if clang/gcc). This is
// technically not necessary but we could be missing something so better be
// safe.
int res = mprotect(memory, mem_size, PROT_READ | PROT_EXEC);
if (res == -1) {
PyErr_SetFromErrno(PyExc_OSError);
Expand Down
15 changes: 4 additions & 11 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1621,7 +1621,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
PyObject *sub = TOP();
PyObject *res = PyDict_GetItemWithError(dict, sub);
if (res == NULL) {
goto binary_subscr_dict_error;
if (!_PyErr_Occurred(tstate)) {
_PyErr_SetKeyError(sub);
}
goto error;
}
Py_INCREF(res);
STACK_SHRINK(1);
Expand Down Expand Up @@ -5193,16 +5196,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH_GOTO();
}

binary_subscr_dict_error:
{
PyObject *sub = POP();
if (!_PyErr_Occurred(tstate)) {
_PyErr_SetKeyError(sub);
}
Py_DECREF(sub);
goto error;
}

unbound_local_error:
{
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
Expand Down

0 comments on commit 6179c2f

Please sign in to comment.