Skip to content

Commit

Permalink
Merge branch 'main' into feat/codecs/surrogate-escape-handler-129173
Browse files Browse the repository at this point in the history
  • Loading branch information
picnixz authored Feb 10, 2025
2 parents 1db1dbb + d7672e5 commit 82ef07a
Show file tree
Hide file tree
Showing 30 changed files with 954 additions and 467 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tail-call.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ on:
- 'Python/bytecodes.c'
- 'Python/ceval.c'
- 'Python/ceval_macros.h'
- 'Python/generated_cases.c.h'
push:
paths:
- 'Python/bytecodes.c'
- 'Python/ceval.c'
- 'Python/ceval_macros.h'
- 'Python/generated_cases.c.h'
workflow_dispatch:

permissions:
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/enum.rst
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ Data Types
* the result is a valid *IntFlag*: an *IntFlag* is returned
* the result is not a valid *IntFlag*: the result depends on the :class:`FlagBoundary` setting

The :func:`repr` of unnamed zero-valued flags has changed. It is now:
The :func:`repr` of unnamed zero-valued flags has changed. It is now::

>>> Color(0)
<Color: 0>
Expand Down
10 changes: 6 additions & 4 deletions Doc/library/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -592,10 +592,12 @@ subclasses. However, the :meth:`!__init__` method in subclasses needs to call

.. method:: Handler.close()

Tidy up any resources used by the handler. This version does no output but
removes the handler from an internal list of handlers which is closed when
:func:`shutdown` is called. Subclasses should ensure that this gets called
from overridden :meth:`close` methods.
Tidy up any resources used by the handler. This version does no output
but removes the handler from an internal map of handlers, which is used
for handler lookup by name.

Subclasses should ensure that this gets called from overridden :meth:`close`
methods.


.. method:: Handler.handle(record)
Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ Deprecated
(Contributed by Victor Stinner in :gh:`120743`.)

* :mod:`pdb`:
The undocumented ``pdb.Pdb.curframe_locals`` attribtue is now a deprecated
The undocumented ``pdb.Pdb.curframe_locals`` attribute is now a deprecated
read-only property. The low overhead dynamic frame locals access added in
Python 3.13 by PEP 667 means the frame locals cache reference previously
stored in this attribute is no longer needed. Derived debuggers should access
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ PyAPI_DATA(Py_ssize_t) _Py_RefTotal;

extern void _Py_AddRefTotal(PyThreadState *, Py_ssize_t);
extern PyAPI_FUNC(void) _Py_IncRefTotal(PyThreadState *);
extern void _Py_DecRefTotal(PyThreadState *);
extern PyAPI_FUNC(void) _Py_DecRefTotal(PyThreadState *);

# define _Py_DEC_REFTOTAL(interp) \
interp->object_state.reftotal--
Expand Down Expand Up @@ -710,7 +710,7 @@ _PyObject_SetMaybeWeakref(PyObject *op)
}
}

extern int _PyObject_ResurrectEndSlow(PyObject *op);
extern PyAPI_FUNC(int) _PyObject_ResurrectEndSlow(PyObject *op);
#endif

// Temporarily resurrects an object during deallocation. The refcount is set
Expand Down
2 changes: 1 addition & 1 deletion Lib/ensurepip/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


__all__ = ["version", "bootstrap"]
_PIP_VERSION = "24.3.1"
_PIP_VERSION = "25.0.1"

# Directory of system wheel packages. Some Linux distribution packaging
# policies recommend against bundling dependencies. For example, Fedora
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion Lib/graphlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def done(self, *nodes):
This method unblocks any successor of each node in *nodes* for being returned
in the future by a call to "get_ready".
Raises :exec:`ValueError` if any node in *nodes* has already been marked as
Raises ValueError if any node in *nodes* has already been marked as
processed by a previous call to this method, if a node was not added to the
graph by using "add" or if called without calling "prepare" previously or if
node has not yet been returned by "get_ready".
Expand Down
1 change: 0 additions & 1 deletion Lib/idlelib/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
"""
import idlelib.pyshell
idlelib.pyshell.main()
# This file does not work for 2.7; See issue 24212.
20 changes: 18 additions & 2 deletions Lib/logging/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,8 @@ def __init__(self, mailhost, fromaddr, toaddrs, subject,
only be used when authentication credentials are supplied. The tuple
will be either an empty tuple, or a single-value tuple with the name
of a keyfile, or a 2-value tuple with the names of the keyfile and
certificate file. (This tuple is passed to the `starttls` method).
certificate file. (This tuple is passed to the
`ssl.SSLContext.load_cert_chain` method).
A timeout in seconds can be specified for the SMTP connection (the
default is one second).
"""
Expand Down Expand Up @@ -1096,8 +1097,23 @@ def emit(self, record):
msg.set_content(self.format(record))
if self.username:
if self.secure is not None:
import ssl

try:
keyfile = self.secure[0]
except IndexError:
keyfile = None

try:
certfile = self.secure[1]
except IndexError:
certfile = None

context = ssl._create_stdlib_context(
certfile=certfile, keyfile=keyfile
)
smtp.ehlo()
smtp.starttls(*self.secure)
smtp.starttls(context=context)
smtp.ehlo()
smtp.login(self.username, self.password)
smtp.send_message(msg)
Expand Down
160 changes: 1 addition & 159 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@
"""

import functools
import io
import posixpath
from errno import EINVAL
from glob import _PathGlobber, _no_recurse_symlinks
from pathlib._os import copyfileobj
from pathlib._os import magic_open, CopyReader, CopyWriter


@functools.cache
Expand All @@ -41,162 +39,6 @@ def _explode_path(path):
return path, names


def magic_open(path, mode='r', buffering=-1, encoding=None, errors=None,
newline=None):
"""
Open the file pointed to by this path and return a file object, as
the built-in open() function does.
"""
try:
return io.open(path, mode, buffering, encoding, errors, newline)
except TypeError:
pass
cls = type(path)
text = 'b' not in mode
mode = ''.join(sorted(c for c in mode if c not in 'bt'))
if text:
try:
attr = getattr(cls, f'__open_{mode}__')
except AttributeError:
pass
else:
return attr(path, buffering, encoding, errors, newline)

try:
attr = getattr(cls, f'__open_{mode}b__')
except AttributeError:
pass
else:
stream = attr(path, buffering)
if text:
stream = io.TextIOWrapper(stream, encoding, errors, newline)
return stream

raise TypeError(f"{cls.__name__} can't be opened with mode {mode!r}")


class CopyReader:
"""
Class that implements the "read" part of copying between path objects.
An instance of this class is available from the ReadablePath._copy_reader
property.
"""
__slots__ = ('_path',)

def __init__(self, path):
self._path = path

_readable_metakeys = frozenset()

def _read_metadata(self, metakeys, *, follow_symlinks=True):
"""
Returns path metadata as a dict with string keys.
"""
raise NotImplementedError


class CopyWriter:
"""
Class that implements the "write" part of copying between path objects. An
instance of this class is available from the WritablePath._copy_writer
property.
"""
__slots__ = ('_path',)

def __init__(self, path):
self._path = path

_writable_metakeys = frozenset()

def _write_metadata(self, metadata, *, follow_symlinks=True):
"""
Sets path metadata from the given dict with string keys.
"""
raise NotImplementedError

def _create(self, source, follow_symlinks, dirs_exist_ok, preserve_metadata):
self._ensure_distinct_path(source)
if preserve_metadata:
metakeys = self._writable_metakeys & source._copy_reader._readable_metakeys
else:
metakeys = None
if not follow_symlinks and source.is_symlink():
self._create_symlink(source, metakeys)
elif source.is_dir():
self._create_dir(source, metakeys, follow_symlinks, dirs_exist_ok)
else:
self._create_file(source, metakeys)
return self._path

def _create_dir(self, source, metakeys, follow_symlinks, dirs_exist_ok):
"""Copy the given directory to our path."""
children = list(source.iterdir())
self._path.mkdir(exist_ok=dirs_exist_ok)
for src in children:
dst = self._path.joinpath(src.name)
if not follow_symlinks and src.is_symlink():
dst._copy_writer._create_symlink(src, metakeys)
elif src.is_dir():
dst._copy_writer._create_dir(src, metakeys, follow_symlinks, dirs_exist_ok)
else:
dst._copy_writer._create_file(src, metakeys)
if metakeys:
metadata = source._copy_reader._read_metadata(metakeys)
if metadata:
self._write_metadata(metadata)

def _create_file(self, source, metakeys):
"""Copy the given file to our path."""
self._ensure_different_file(source)
with magic_open(source, 'rb') as source_f:
try:
with magic_open(self._path, 'wb') as target_f:
copyfileobj(source_f, target_f)
except IsADirectoryError as e:
if not self._path.exists():
# Raise a less confusing exception.
raise FileNotFoundError(
f'Directory does not exist: {self._path}') from e
raise
if metakeys:
metadata = source._copy_reader._read_metadata(metakeys)
if metadata:
self._write_metadata(metadata)

def _create_symlink(self, source, metakeys):
"""Copy the given symbolic link to our path."""
self._path.symlink_to(source.readlink())
if metakeys:
metadata = source._copy_reader._read_metadata(metakeys, follow_symlinks=False)
if metadata:
self._write_metadata(metadata, follow_symlinks=False)

def _ensure_different_file(self, source):
"""
Raise OSError(EINVAL) if both paths refer to the same file.
"""
pass

def _ensure_distinct_path(self, source):
"""
Raise OSError(EINVAL) if the other path is within this path.
"""
# Note: there is no straightforward, foolproof algorithm to determine
# if one directory is within another (a particularly perverse example
# would be a single network share mounted in one location via NFS, and
# in another location via CIFS), so we simply checks whether the
# other path is lexically equal to, or within, this path.
if source == self._path:
err = OSError(EINVAL, "Source and target are the same path")
elif source in self._path.parents:
err = OSError(EINVAL, "Source path is a parent of target path")
else:
return
err.filename = str(source)
err.filename2 = str(self._path)
raise err


class JoinablePath:
"""Base class for pure path objects.
Expand Down
Loading

0 comments on commit 82ef07a

Please sign in to comment.