Skip to content

Commit

Permalink
Merge branch 'main' into pathlib-abc-io-redux
Browse files Browse the repository at this point in the history
  • Loading branch information
barneygale authored Dec 24, 2023
2 parents b3a7c27 + 0c57454 commit 16649ba
Show file tree
Hide file tree
Showing 49 changed files with 655 additions and 377 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ Doc/c-api/stable.rst @encukou

**/*dataclasses* @ericvsmith

**/*ensurepip* @pfmoore @pradyunsg

**/*idlelib* @terryjreedy

**/*typing* @JelleZijlstra @AlexWaygood
Expand Down
4 changes: 3 additions & 1 deletion Doc/library/datetime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,8 @@ Other constructor:

Examples::

.. doctest::

>>> from datetime import time
>>> time.fromisoformat('04:23:01')
datetime.time(4, 23, 1)
Expand All @@ -1808,7 +1810,7 @@ Other constructor:
datetime.time(4, 23, 1)
>>> time.fromisoformat('04:23:01.000384')
datetime.time(4, 23, 1, 384)
>>> time.fromisoformat('04:23:01,000')
>>> time.fromisoformat('04:23:01,000384')
datetime.time(4, 23, 1, 384)
>>> time.fromisoformat('04:23:01+04:00')
datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
Expand Down
7 changes: 7 additions & 0 deletions Doc/library/dbm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,13 @@ This module can be used with the "classic" ndbm interface or the GNU GDBM
compatibility interface. On Unix, the :program:`configure` script will attempt
to locate the appropriate header file to simplify building this module.

.. warning::

The ndbm library shipped as part of macOS has an undocumented limitation on the
size of values, which can result in corrupted database files
when storing values larger than this limit. Reading such corrupted files can
result in a hard crash (segmentation fault).

.. exception:: error

Raised on :mod:`dbm.ndbm`-specific errors, such as I/O errors. :exc:`KeyError` is raised
Expand Down
8 changes: 6 additions & 2 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1001,11 +1001,14 @@ as internal buffering of data.

.. audit-event:: os.chmod path,mode,dir_fd os.fchmod

.. availability:: Unix.
.. availability:: Unix, Windows.

The function is limited on Emscripten and WASI, see
:ref:`wasm-availability` for more information.

.. versionchanged:: 3.13
Added support on Windows.


.. function:: fchown(fd, uid, gid)

Expand Down Expand Up @@ -2077,7 +2080,8 @@ features:
Accepts a :term:`path-like object`.

.. versionchanged:: 3.13
Added support for the *follow_symlinks* argument on Windows.
Added support for a file descriptor and the *follow_symlinks* argument
on Windows.


.. function:: chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)
Expand Down
3 changes: 3 additions & 0 deletions Doc/library/shelve.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ Restrictions
differs across Unix versions and requires knowledge about the database
implementation used.

* On macOS :mod:`dbm.ndbm` can silently corrupt the database file on updates,
which can cause hard crashes when trying to read from the database.


.. class:: Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')

Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ os
``False`` on Windows.
(Contributed by Serhiy Storchaka in :gh:`59616`)

* Add support of :func:`os.fchmod` and a file descriptor
in :func:`os.chmod` on Windows.
(Contributed by Serhiy Storchaka in :gh:`113191`)

* :func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned
process use the current process environment.
(Contributed by Jakub Kulik in :gh:`113119`.)
Expand Down
3 changes: 2 additions & 1 deletion Lib/asyncio/base_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ def close(self):

try:
self._proc.kill()
except ProcessLookupError:
except (ProcessLookupError, PermissionError):
# the process may have already exited or may be running setuid
pass

# Don't clear the _proc reference yet: _post_init() may still run
Expand Down
6 changes: 6 additions & 0 deletions Lib/idlelib/idle_test/test_calltip.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import types
import re
from idlelib.idle_test.mock_tk import Text
from test.support import MISSING_C_DOCSTRINGS


# Test Class TC is used in multiple get_argspec test methods
Expand Down Expand Up @@ -50,6 +51,8 @@ class Get_argspecTest(unittest.TestCase):
# but a red buildbot is better than a user crash (as has happened).
# For a simple mismatch, change the expected output to the actual.

@unittest.skipIf(MISSING_C_DOCSTRINGS,
"Signature information for builtins requires docstrings")
def test_builtins(self):

def tiptest(obj, out):
Expand Down Expand Up @@ -143,6 +146,8 @@ def f(): pass
f.__doc__ = 'a'*300
self.assertEqual(get_spec(f), f"()\n{'a'*(calltip._MAX_COLS-3) + '...'}")

@unittest.skipIf(MISSING_C_DOCSTRINGS,
"Signature information for builtins requires docstrings")
def test_multiline_docstring(self):
# Test fewer lines than max.
self.assertEqual(get_spec(range),
Expand All @@ -157,6 +162,7 @@ def test_multiline_docstring(self):
bytes(int) -> bytes object of size given by the parameter initialized with null bytes
bytes() -> empty bytes object''')

def test_multiline_docstring_2(self):
# Test more than max lines
def f(): pass
f.__doc__ = 'a\n' * 15
Expand Down
8 changes: 4 additions & 4 deletions Lib/multiprocessing/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@

def sub_debug(msg, *args):
if _logger:
_logger.log(SUBDEBUG, msg, *args)
_logger.log(SUBDEBUG, msg, *args, stacklevel=2)

def debug(msg, *args):
if _logger:
_logger.log(DEBUG, msg, *args)
_logger.log(DEBUG, msg, *args, stacklevel=2)

def info(msg, *args):
if _logger:
_logger.log(INFO, msg, *args)
_logger.log(INFO, msg, *args, stacklevel=2)

def sub_warning(msg, *args):
if _logger:
_logger.log(SUBWARNING, msg, *args)
_logger.log(SUBWARNING, msg, *args, stacklevel=2)

def get_logger():
'''
Expand Down
1 change: 1 addition & 0 deletions Lib/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ def _add(str, fn):
_set = set()
_add("HAVE_FCHDIR", "chdir")
_add("HAVE_FCHMOD", "chmod")
_add("MS_WINDOWS", "chmod")
_add("HAVE_FCHOWN", "chown")
_add("HAVE_FDOPENDIR", "listdir")
_add("HAVE_FDOPENDIR", "scandir")
Expand Down
14 changes: 7 additions & 7 deletions Lib/pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,13 +857,13 @@ def save_str(self, obj):
else:
self.write(BINUNICODE + pack("<I", n) + encoded)
else:
obj = obj.replace("\\", "\\u005c")
obj = obj.replace("\0", "\\u0000")
obj = obj.replace("\n", "\\u000a")
obj = obj.replace("\r", "\\u000d")
obj = obj.replace("\x1a", "\\u001a") # EOF on DOS
self.write(UNICODE + obj.encode('raw-unicode-escape') +
b'\n')
# Escape what raw-unicode-escape doesn't, but memoize the original.
tmp = obj.replace("\\", "\\u005c")
tmp = tmp.replace("\0", "\\u0000")
tmp = tmp.replace("\n", "\\u000a")
tmp = tmp.replace("\r", "\\u000d")
tmp = tmp.replace("\x1a", "\\u001a") # EOF on DOS
self.write(UNICODE + tmp.encode('raw-unicode-escape') + b'\n')
self.memoize(obj)
dispatch[str] = save_str

Expand Down
7 changes: 6 additions & 1 deletion Lib/shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,12 @@ def copymode(src, dst, *, follow_symlinks=True):
else:
return
else:
stat_func, chmod_func = _stat, os.chmod
stat_func = _stat
if os.name == 'nt' and os.path.islink(dst):
def chmod_func(*args):
os.chmod(*args, follow_symlinks=True)
else:
chmod_func = os.chmod

st = stat_func(src)
chmod_func(dst, stat.S_IMODE(st.st_mode))
Expand Down
6 changes: 4 additions & 2 deletions Lib/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@


def _int_to_enum(value, enum_klass):
"""Convert a numeric value to an IntEnum member.
If it's not a known member, return the numeric value itself.
"""Convert a possible numeric value to an IntEnum member.
If it's not a known member, return the value itself.
"""
if not isinstance(value, int):
return value
try:
return enum_klass(value)
except ValueError:
Expand Down
23 changes: 23 additions & 0 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4724,6 +4724,29 @@ def test_level(self):
root_logger.setLevel(root_level)
logger.setLevel(level=LOG_LEVEL)

def test_filename(self):
logger = multiprocessing.get_logger()
original_level = logger.level
try:
logger.setLevel(util.DEBUG)
stream = io.StringIO()
handler = logging.StreamHandler(stream)
logging_format = '[%(levelname)s] [%(filename)s] %(message)s'
handler.setFormatter(logging.Formatter(logging_format))
logger.addHandler(handler)
logger.info('1')
util.info('2')
logger.debug('3')
filename = os.path.basename(__file__)
log_record = stream.getvalue()
self.assertIn(f'[INFO] [{filename}] 1', log_record)
self.assertIn(f'[INFO] [{filename}] 2', log_record)
self.assertIn(f'[DEBUG] [{filename}] 3', log_record)
finally:
logger.setLevel(original_level)
logger.removeHandler(handler)
handler.close()


# class _TestLoggingProcessName(BaseTestCase):
#
Expand Down
8 changes: 8 additions & 0 deletions Lib/test/pickletester.py
Original file line number Diff line number Diff line change
Expand Up @@ -1825,6 +1825,14 @@ def test_unicode_high_plane(self):
t2 = self.loads(p)
self.assert_is_copy(t, t2)

def test_unicode_memoization(self):
# Repeated str is re-used (even when escapes added).
for proto in protocols:
for s in '', 'xyz', 'xyz\n', 'x\\yz', 'x\xa1yz\r':
p = self.dumps((s, s), proto)
s1, s2 = self.loads(p)
self.assertIs(s1, s2)

def test_bytes(self):
for proto in protocols:
for s in b'', b'xyz', b'xyz'*100:
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,8 @@ def collect_windows(info_add):
stderr=subprocess.PIPE,
text=True)
output = proc.communicate()[0]
if proc.returncode == 0xc0000142:
return
if proc.returncode:
output = ""
except OSError:
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/test_asyncio/test_runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,24 @@ async def coro():
self.assertEqual(1, policy.set_event_loop.call_count)
runner.close()

def test_no_repr_is_call_on_the_task_result(self):
# See https://github.com/python/cpython/issues/112559.
class MyResult:
def __init__(self):
self.repr_count = 0
def __repr__(self):
self.repr_count += 1
return super().__repr__()

async def coro():
return MyResult()


with asyncio.Runner() as runner:
result = runner.run(coro())

self.assertEqual(0, result.repr_count)


if __name__ == '__main__':
unittest.main()
2 changes: 2 additions & 0 deletions Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,8 @@ def __del__(self):
del L
self.assertEqual(PyList.num, 0)

@unittest.skipIf(MISSING_C_DOCSTRINGS,
"Signature information for builtins requires docstrings")
def test_heap_ctype_doc_and_text_signature(self):
self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc")
self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)")
Expand Down
Loading

0 comments on commit 16649ba

Please sign in to comment.