Skip to content

Commit

Permalink
Merge branch '3.13' into backport-a38fef4-3.13
Browse files Browse the repository at this point in the history
  • Loading branch information
Yhg1s authored Dec 2, 2024
2 parents cd4753e + 511c588 commit 61d5169
Show file tree
Hide file tree
Showing 17 changed files with 1,838 additions and 340 deletions.
21 changes: 21 additions & 0 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,13 @@ iterations of the loop.
This opcode is now only used in situations where the local variable is
guaranteed to be initialized. It cannot raise :exc:`UnboundLocalError`.

.. opcode:: LOAD_FAST_LOAD_FAST (var_nums)

Pushes references to ``co_varnames[var_nums >> 4]`` and
``co_varnames[var_nums & 15]`` onto the stack.

.. versionadded:: 3.13

.. opcode:: LOAD_FAST_CHECK (var_num)

Pushes a reference to the local ``co_varnames[var_num]`` onto the stack,
Expand All @@ -1403,6 +1410,20 @@ iterations of the loop.

Stores ``STACK.pop()`` into the local ``co_varnames[var_num]``.

.. opcode:: STORE_FAST_STORE_FAST (var_nums)

Stores ``STACK[-1]`` into ``co_varnames[var_nums >> 4]``
and ``STACK[-2]`` into ``co_varnames[var_nums & 15]``.

.. versionadded:: 3.13

.. opcode:: STORE_FAST_LOAD_FAST (var_nums)

Stores ``STACK.pop()`` into the local ``co_varnames[var_nums >> 4]``
and pushes a reference to the local ``co_varnames[var_nums & 15]``
onto the stack.

.. versionadded:: 3.13

.. opcode:: DELETE_FAST (var_num)

Expand Down
5 changes: 5 additions & 0 deletions Doc/library/string.rst
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,11 @@ The available presentation types for :class:`float` and
| | as altered by the other format modifiers. |
+---------+----------------------------------------------------------+

The result should be correctly rounded to a given precision ``p`` of digits
after the decimal point. The rounding mode for :class:`float` matches that
of the :func:`round` builtin. For :class:`~decimal.Decimal`, the rounding
mode of the current :ref:`context <decimal-context>` will be used.

The available presentation types for :class:`complex` are the same as those for
:class:`float` (``'%'`` is not allowed). Both the real and imaginary components
of a complex number are formatted as floating-point numbers, according to the
Expand Down
33 changes: 11 additions & 22 deletions Doc/reference/simple_stmts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,9 @@ The extended form, ``assert expression1, expression2``, is equivalent to ::

These equivalences assume that :const:`__debug__` and :exc:`AssertionError` refer to
the built-in variables with those names. In the current implementation, the
built-in variable :const:`__debug__` is ``True`` under normal circumstances,
built-in variable ``__debug__`` is ``True`` under normal circumstances,
``False`` when optimization is requested (command line option :option:`-O`). The current
code generator emits no code for an assert statement when optimization is
code generator emits no code for an :keyword:`assert` statement when optimization is
requested at compile time. Note that it is unnecessary to include the source
code for the expression that failed in the error message; it will be displayed
as part of the stack trace.
Expand Down Expand Up @@ -531,8 +531,8 @@ The :keyword:`!yield` statement
yield_stmt: `yield_expression`

A :keyword:`yield` statement is semantically equivalent to a :ref:`yield
expression <yieldexpr>`. The yield statement can be used to omit the parentheses
that would otherwise be required in the equivalent yield expression
expression <yieldexpr>`. The ``yield`` statement can be used to omit the
parentheses that would otherwise be required in the equivalent yield expression
statement. For example, the yield statements ::

yield <expr>
Expand All @@ -544,7 +544,7 @@ are equivalent to the yield expression statements ::
(yield from <expr>)

Yield expressions and statements are only used when defining a :term:`generator`
function, and are only used in the body of the generator function. Using yield
function, and are only used in the body of the generator function. Using :keyword:`yield`
in a function definition is sufficient to cause that definition to create a
generator function instead of a normal function.

Expand Down Expand Up @@ -964,25 +964,14 @@ The :keyword:`!global` statement
.. productionlist:: python-grammar
global_stmt: "global" `identifier` ("," `identifier`)*

The :keyword:`global` statement is a declaration which holds for the entire
current code block. It means that the listed identifiers are to be interpreted
as globals. It would be impossible to assign to a global variable without
The :keyword:`global` statement causes the listed identifiers to be interpreted
as globals. It would be impossible to assign to a global variable without
:keyword:`!global`, although free variables may refer to globals without being
declared global.

Names listed in a :keyword:`global` statement must not be used in the same code
block textually preceding that :keyword:`!global` statement.

Names listed in a :keyword:`global` statement must not be defined as formal
parameters, or as targets in :keyword:`with` statements or :keyword:`except` clauses, or in a :keyword:`for` target list, :keyword:`class`
definition, function definition, :keyword:`import` statement, or variable
annotation.

.. impl-detail::

The current implementation does not enforce some of these restrictions, but
programs should not abuse this freedom, as future implementations may enforce
them or silently change the meaning of the program.
The :keyword:`global` statement applies to the entire scope of a function or
class body. A :exc:`SyntaxError` is raised if a variable is used or
assigned to prior to its global declaration in the scope.

.. index::
pair: built-in function; exec
Expand Down Expand Up @@ -1018,7 +1007,7 @@ identifiers. If a name is bound in more than one nonlocal scope, the
nearest binding is used. If a name is not bound in any nonlocal scope,
or if there is no nonlocal scope, a :exc:`SyntaxError` is raised.

The nonlocal statement applies to the entire scope of a function or
The :keyword:`nonlocal` statement applies to the entire scope of a function or
class body. A :exc:`SyntaxError` is raised if a variable is used or
assigned to prior to its nonlocal declaration in the scope.

Expand Down
5 changes: 5 additions & 0 deletions Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
#ifdef Py_TRACE_REFS
_Py_ForgetReference(op);
#endif
struct _reftracer_runtime_state *tracer = &_PyRuntime.ref_tracer;
if (tracer->tracer_func != NULL) {
void* data = tracer->tracer_data;
tracer->tracer_func(op, PyRefTracer_DESTROY, data);
}
destruct(op);
}
}
Expand Down
3 changes: 2 additions & 1 deletion Lib/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ def _showtraceback(self, typ, value, tb, source):
# Set the line of text that the exception refers to
lines = source.splitlines()
if (source and typ is SyntaxError
and not value.text and len(lines) >= value.lineno):
and not value.text and value.lineno is not None
and len(lines) >= value.lineno):
value.text = lines[value.lineno - 1]
sys.last_exc = sys.last_value = value = value.with_traceback(tb)
if sys.excepthook is sys.__excepthook__:
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_pyrepl/test_interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ def test_runsource_shows_syntax_error_for_failed_compilation(self):
console.runsource(source)
mock_showsyntaxerror.assert_called_once()

def test_runsource_survives_null_bytes(self):
console = InteractiveColoredConsole()
source = "\x00\n"
f = io.StringIO()
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
result = console.runsource(source)
self.assertFalse(result)
self.assertIn("source code string cannot contain null bytes", f.getvalue())

def test_no_active_future(self):
console = InteractiveColoredConsole()
source = dedent("""\
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_pyrepl/test_pyrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,11 @@ def test_proper_tracebacklimit(self):
self.assertIn("in x3", output)
self.assertIn("in <module>", output)

def test_null_byte(self):
output, exit_code = self.run_repl("\x00\nexit()\n")
self.assertEqual(exit_code, 0)
self.assertNotIn("TypeError", output)

def test_readline_history_file(self):
# skip, if readline module is not available
readline = import_module('readline')
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_sqlite3/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ def test_table_lock_cursor_dealloc(self):
con.commit()
cur = con.execute("select t from t")
del cur
support.gc_collect()
con.execute("drop table t")
con.commit()

Expand All @@ -448,6 +449,7 @@ def dup(v):
con.create_function("dup", 1, dup)
cur = con.execute("select dup(t) from t")
del cur
support.gc_collect()
con.execute("drop table t")
con.commit()

Expand Down
52 changes: 52 additions & 0 deletions Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import sys
import unittest
import unittest.mock
from ast import literal_eval
from threading import Thread
from test import support
from test.support import import_helper
from test.support import os_helper
Expand Down Expand Up @@ -304,11 +306,19 @@ def test_wrap_socket(sock, *,
return context.wrap_socket(sock, **kwargs)


USE_SAME_TEST_CONTEXT = False
_TEST_CONTEXT = None

def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True):
"""Create context
client_context, server_context, hostname = testing_context()
"""
global _TEST_CONTEXT
if USE_SAME_TEST_CONTEXT:
if _TEST_CONTEXT is not None:
return _TEST_CONTEXT

if server_cert == SIGNED_CERTFILE:
hostname = SIGNED_CERTFILE_HOSTNAME
elif server_cert == SIGNED_CERTFILE2:
Expand All @@ -326,6 +336,10 @@ def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True):
if server_chain:
server_context.load_verify_locations(SIGNING_CA)

if USE_SAME_TEST_CONTEXT:
if _TEST_CONTEXT is not None:
_TEST_CONTEXT = client_context, server_context, hostname

return client_context, server_context, hostname


Expand Down Expand Up @@ -2834,6 +2848,44 @@ def test_echo(self):
'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
str(e.exception))

@unittest.skipUnless(support.Py_GIL_DISABLED, "test is only useful if the GIL is disabled")
def test_ssl_in_multiple_threads(self):
# See GH-124984: OpenSSL is not thread safe.
threads = []

global USE_SAME_TEST_CONTEXT
USE_SAME_TEST_CONTEXT = True
try:
for func in (
self.test_echo,
self.test_alpn_protocols,
self.test_getpeercert,
self.test_crl_check,
self.test_check_hostname_idn,
self.test_wrong_cert_tls12,
self.test_wrong_cert_tls13,
):
# Be careful with the number of threads here.
# Too many can result in failing tests.
for num in range(5):
with self.subTest(func=func, num=num):
threads.append(Thread(target=func))

with threading_helper.catch_threading_exception() as cm:
for thread in threads:
with self.subTest(thread=thread):
thread.start()

for thread in threads:
with self.subTest(thread=thread):
thread.join()
if cm.exc_value is not None:
# Some threads can skip their test
if not isinstance(cm.exc_value, unittest.SkipTest):
raise cm.exc_value
finally:
USE_SAME_TEST_CONTEXT = False

def test_getpeercert(self):
if support.verbose:
sys.stdout.write("\n")
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4254,6 +4254,9 @@ class CustomProtocol(TestCase, Protocol):
class CustomContextManager(typing.ContextManager, Protocol):
pass

class CustomAsyncIterator(typing.AsyncIterator, Protocol):
pass

def test_non_runtime_protocol_isinstance_check(self):
class P(Protocol):
x: int
Expand Down
3 changes: 2 additions & 1 deletion Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1989,7 +1989,8 @@ def _allow_reckless_class_checks(depth=2):
_PROTO_ALLOWLIST = {
'collections.abc': [
'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable',
'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer',
'AsyncIterator', 'Hashable', 'Sized', 'Container', 'Collection',
'Reversible', 'Buffer',
],
'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'],
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Correctly honour :mod:`tracemalloc` hooks in specialized ``Py_DECREF``
paths. Patch by Pablo Galindo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed thread safety in :mod:`ssl` in the free-threaded build. OpenSSL operations are now protected by a per-object lock.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Avoid the exiting the interpreter if a null byte is given as input in the new REPL.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow :class:`collections.abc.AsyncIterator` to be a base for Protocols.
Loading

0 comments on commit 61d5169

Please sign in to comment.