Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/howto/mro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The Python 2.3 Method Resolution Order
The Method Resolution Order discussed here was *introduced* in Python 2.3,
but it is still used in later versions -- including Python 3.

By `Michele Simionato <https://www.phyast.pitt.edu/~micheles/>`__.
By `Michele Simionato <https://github.com/micheles>`__.

:Abstract:

Expand Down
15 changes: 9 additions & 6 deletions Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ hash supplied more than 2047 bytes of data at once in its constructor or
.. index:: single: OpenSSL; (use in module hashlib)

Constructors for hash algorithms that are always present in this module are
:func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`, :func:`sha512`,
:func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`, :func:`sha3_512`,
:func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and :func:`blake2s`.
:func:`md5` is normally available as well, though it may be missing or blocked
if you are using a rare "FIPS compliant" build of Python.
These correspond to :data:`algorithms_guaranteed`.
:func:`md5`, :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`,
:func:`sha512`, :func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`,
:func:`sha3_512`, :func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and
:func:`blake2s`. These correspond to :data:`algorithms_guaranteed`.

Any of these may nonetheless be missing or blocked in unusual environments,
such as a rare "FIPS compliant" build of Python or when OpenSSL's "FIPS mode"
is configured to exclude some algorithms from its default provider. Calling
the constructor of an algorithm that is unavailable raises :exc:`ValueError`.

Additional algorithms may also be available if your Python distribution's
:mod:`!hashlib` was linked against a build of OpenSSL that provides others.
Expand Down
15 changes: 1 addition & 14 deletions Doc/library/numbers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,7 @@ Notes for type implementers

Implementers should be careful to make equal numbers equal and hash
them to the same values. This may be subtle if there are two different
extensions of the real numbers. For example, :class:`fractions.Fraction`
implements :func:`hash` as follows::

def __hash__(self):
if self.denominator == 1:
# Get integers right.
return hash(self.numerator)
# Expensive check, but definitely correct.
if self == float(self):
return hash(float(self))
else:
# Use tuple's hash to avoid a high collision rate on
# simple fractions.
return hash((self.numerator, self.denominator))
extensions of the real numbers. See also :ref:`numeric-hash`.


Adding More Numeric ABCs
Expand Down
11 changes: 10 additions & 1 deletion Doc/library/tkinter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2699,7 +2699,8 @@ Base and mixin classes
Make *widget* a stand-alone top-level window, decorated by the window
manager with a title bar and so on.
Only :class:`Frame`, :class:`LabelFrame` and :class:`Toplevel` widgets
may be used; passing any other widget type raises an error.
may be used (the :mod:`tkinter.ttk` versions are **not** accepted);
passing any other widget type raises an error.
:meth:`wm_manage` is an alias of :meth:`!manage`.

.. versionadded:: 3.3
Expand Down Expand Up @@ -3393,6 +3394,14 @@ Toplevel widgets
profile files is the :envvar:`HOME` environment variable or, if that
isn't defined, then :data:`os.curdir`.

.. note::

On Windows, creating a Tcl interpreter (by instantiating :class:`Tk` or
calling :func:`Tcl`) sets the :envvar:`HOME` environment variable for
the process, if it is not already set, to ``%HOMEDRIVE%%HOMEPATH%`` (or
:envvar:`USERPROFILE`, or ``c:\``). This is done by Tcl and can affect
other code that reads :envvar:`HOME`.

.. attribute:: tk

The Tk application object created by instantiating :class:`Tk`. This
Expand Down
12 changes: 5 additions & 7 deletions Lib/hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,15 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
return digestobj


__logging = None
for __func_name in __always_supported:
# try them all, some may not work due to the OpenSSL
# version not supporting that algorithm.
try:
globals()[__func_name] = __get_hash(__func_name)
except ValueError as __exc:
import logging as __logging
__logging.error('hash algorithm %s will not be supported at runtime '
'[reason: %s]', __func_name, __exc)
except ValueError:
# Don't log here: logging at import time has global side effects and
# would tell the wrong audience; code that uses a missing algorithm
# gets a ValueError from the stub installed below.
# The following code can be simplified in Python 3.19
# once "string" is removed from the signature.
__code = f'''\
Expand All @@ -291,9 +290,8 @@ def {__func_name}(data=__UNSET, *, usedforsecurity=True, string=__UNSET):
'''
exec(__code, {"__UNSET": object()}, __locals := {})
globals()[__func_name] = __locals[__func_name]
del __exc, __code, __locals
del __code, __locals

# Cleanup locals()
del __always_supported, __func_name, __get_hash
del __py_new, __hash_new, __get_openssl_constructor
del __logging
5 changes: 5 additions & 0 deletions Lib/idlelib/News3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Released on 2026-10-01
=========================


gh-85320: IDLE now reads and writes its configuration files and the
breakpoints file using UTF-8 instead of the locale encoding.
Files with non-ASCII characters and non-UTF-8 encoding may need
to be opened in an editor and resaved with UTF-8 encoding.

gh-143774: Better explain the operation of Format / Format Paragraph.
Patch by Terry J. Reedy.

Expand Down
9 changes: 5 additions & 4 deletions Lib/idlelib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ def GetOptionList(self, section):

def Load(self):
"Load the configuration file from disk."
if self.file:
self.read(self.file)
if self.file and os.path.exists(self.file):
with open(self.file, encoding='utf-8', errors='replace') as f:
self.read_file(f)

class IdleUserConfParser(IdleConfParser):
"""
Expand Down Expand Up @@ -133,10 +134,10 @@ def Save(self):
if fname and fname[0] != '#':
if not self.IsEmpty():
try:
cfgFile = open(fname, 'w')
cfgFile = open(fname, 'w', encoding='utf-8')
except OSError:
os.unlink(fname)
cfgFile = open(fname, 'w')
cfgFile = open(fname, 'w', encoding='utf-8')
with cfgFile:
self.write(cfgFile)
elif os.path.exists(self.file):
Expand Down
8 changes: 5 additions & 3 deletions Lib/idlelib/pyshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ def store_file_breaks(self):
breaks = self.breakpoints
filename = self.io.filename
try:
with open(self.breakpointPath) as fp:
with open(self.breakpointPath,
encoding='utf-8', errors='replace') as fp:
lines = fp.readlines()
except OSError:
lines = []
try:
with open(self.breakpointPath, "w") as new_file:
with open(self.breakpointPath, "w", encoding='utf-8') as new_file:
for line in lines:
if not line.startswith(filename + '='):
new_file.write(line)
Expand All @@ -272,7 +273,8 @@ def restore_file_breaks(self):
if filename is None:
return
if os.path.isfile(self.breakpointPath):
with open(self.breakpointPath) as fp:
with open(self.breakpointPath,
encoding='utf-8', errors='replace') as fp:
lines = fp.readlines()
for line in lines:
if line.startswith(filename + '='):
Expand Down
2 changes: 1 addition & 1 deletion Lib/ntpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def _isreservedname(name):
def expanduser(path):
"""Expand ~ and ~user constructs.

If user or $HOME is unknown, do nothing."""
If user or home directory is unknown, do nothing."""
path = os.fspath(path)
if isinstance(path, bytes):
seps = b'\\/'
Expand Down
55 changes: 55 additions & 0 deletions Lib/test/test_tkinter/test_tkinter_pipe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# test_tkinter_pipe.py
import unittest
import subprocess
import sys
from test import support


@unittest.skipUnless(support.has_subprocess_support, "test requires subprocess")
class TkinterPipeTest(unittest.TestCase):

def test_tkinter_pipe_buffered(self):
args = [sys.executable, "-i"]
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b"import tkinter\n")
proc.stdin.write(b"interpreter = tkinter.Tcl()\n")
proc.stdin.write(b"print('hello')\n")
proc.stdin.write(b"print('goodbye')\n")
proc.stdin.write(b"quit()\n")
stdout, stderr = proc.communicate(timeout=support.SHORT_TIMEOUT)
stdout = stdout.decode()
self.assertEqual(stdout.split(), ['hello', 'goodbye'])

def test_tkinter_pipe_unbuffered(self):
args = [sys.executable, "-i", "-u"]
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b"import tkinter\n")
proc.stdin.write(b"interpreter = tkinter.Tcl()\n")

proc.stdin.write(b"print('hello')\n")
proc.stdin.flush()
stdout = proc.stdout.readline()
stdout = stdout.decode()
self.assertEqual(stdout.strip(), 'hello')

proc.stdin.write(b"print('hello again')\n")
proc.stdin.flush()
stdout = proc.stdout.readline()
stdout = stdout.decode()
self.assertEqual(stdout.strip(), 'hello again')

proc.stdin.write(b"print('goodbye')\n")
proc.stdin.write(b"quit()\n")
stdout, stderr = proc.communicate(timeout=support.SHORT_TIMEOUT)
stdout = stdout.decode()
self.assertEqual(stdout.strip(), 'goodbye')


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix C stack unwinding tests on Linux LoongArch builds by teaching the manual
frame pointer unwinder to recognize the LoongArch frame layout.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix undefined behaviour when a :mod:`sys.monitoring` callback raised an
exception while the program was following a branch or loop.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
IDLE now reads and writes its configuration files and the breakpoints file
using UTF-8 instead of the locale encoding. This keeps non-ASCII data (such
as non-ASCII paths) from being corrupted and makes the files portable between
environments.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Importing :mod:`hashlib` no longer logs an error to stderr when a normally
guaranteed hash algorithm is unavailable in the current runtime (for example
under an OpenSSL FIPS configuration or a build using
:option:`--without-builtin-hashlib-hashes <--with-builtin-hashlib-hashes>`).
Code that actually uses the missing algorithm still gets a clear
:exc:`ValueError`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Prevent :mod:`tkinter` from hanging on Windows if stdin is redirected to a pipe in an
interactive session. This is helpful for testing interactive usage of
tkinter from a script, for example as part of the cpython test suite.
6 changes: 6 additions & 0 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ static const uintptr_t min_frame_pointer_addr = 0x1000;
// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
# define FRAME_POINTER_NEXT_OFFSET 0
# define FRAME_POINTER_RETURN_OFFSET 2
#elif defined(__loongarch__)
// On LoongArch, the frame pointer is the caller's stack pointer.
// The saved frame pointer is stored at fp[-2], and the return
// address is stored at fp[-1].
# define FRAME_POINTER_NEXT_OFFSET -2
# define FRAME_POINTER_RETURN_OFFSET -1
#else
# define FRAME_POINTER_NEXT_OFFSET 0
# define FRAME_POINTER_RETURN_OFFSET 1
Expand Down
32 changes: 25 additions & 7 deletions Modules/_tkinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -3443,10 +3443,10 @@ static PyMethodDef moduleMethods[] =
};

#ifdef WAIT_FOR_STDIN
#ifndef MS_WINDOWS

static int stdin_ready = 0;

#ifndef MS_WINDOWS
static void
MyFileProc(void *clientData, int mask)
{
Expand All @@ -3465,22 +3465,40 @@ static PyThreadState *event_tstate = NULL;
static int
EventHook(void)
{
#ifndef MS_WINDOWS
#ifdef MS_WINDOWS
HANDLE hStdin;
DWORD type;
#else
int tfile;
stdin_ready = 0;
#endif
PyEval_RestoreThread(event_tstate);
stdin_ready = 0;
errorInCmd = 0;
#ifndef MS_WINDOWS
#ifdef MS_WINDOWS
hStdin = GetStdHandle(STD_INPUT_HANDLE);
type = GetFileType(hStdin);
while (1) {
#else
tfile = fileno(stdin);
Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc,
(void *)(Py_intptr_t)tfile);
#endif
while (!stdin_ready) {
#endif
int result;
#ifdef MS_WINDOWS
if (_kbhit()) {
stdin_ready = 1;
if (type == FILE_TYPE_CHAR) {
if (_kbhit()) break;
}
else if (type == FILE_TYPE_PIPE) {
DWORD available;
if (PeekNamedPipe(hStdin, NULL, 0, NULL, &available, NULL)) {
if (available > 0) break;
}
else {
if (GetLastError() == ERROR_BROKEN_PIPE) break;
}
}
else if (type == FILE_TYPE_DISK) {
break;
}
#endif
Expand Down
7 changes: 4 additions & 3 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,15 @@ static void dtrace_function_return(_PyInterpreterFrame *);
// for an exception handler, displaying the traceback, and so on
#define INSTRUMENTED_JUMP(src, dest, event) \
do { \
_Py_CODEUNIT *_dest = (dest); \
if (tstate->tracing) {\
next_instr = dest; \
next_instr = _dest; \
} else { \
_PyFrame_SetStackPointer(frame, stack_pointer); \
next_instr = _Py_call_instrumentation_jump(this_instr, tstate, event, frame, src, dest); \
next_instr = _Py_call_instrumentation_jump(this_instr, tstate, event, frame, src, _dest); \
stack_pointer = _PyFrame_GetStackPointer(frame); \
if (next_instr == NULL) { \
next_instr = (dest)+1; \
next_instr = _dest + 1; \
JUMP_TO_LABEL(error); \
} \
} \
Expand Down
Loading