Skip to content

Update some libraries to 3.13.3 #5731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 22, 2025
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 Lib/colorsys.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
__all__ = ["rgb_to_yiq","yiq_to_rgb","rgb_to_hls","hls_to_rgb",
"rgb_to_hsv","hsv_to_rgb"]

# Some floating point constants
# Some floating-point constants

ONE_THIRD = 1.0/3.0
ONE_SIXTH = 1.0/6.0
Expand Down
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
91 changes: 70 additions & 21 deletions Lib/linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@
that name.
"""

import functools
import sys
import os
import tokenize

__all__ = ["getline", "clearcache", "checkcache", "lazycache"]


# The cache. Maps filenames to either a thunk which will provide source code,
# or a tuple (size, mtime, lines, fullname) once loaded.
cache = {}
_interactive_cache = {}


def clearcache():
Expand Down Expand Up @@ -49,28 +45,54 @@ def getlines(filename, module_globals=None):
return []


def _getline_from_code(filename, lineno):
lines = _getlines_from_code(filename)
if 1 <= lineno <= len(lines):
return lines[lineno - 1]
return ''

def _make_key(code):
return (code.co_filename, code.co_qualname, code.co_firstlineno)

def _getlines_from_code(code):
code_id = _make_key(code)
if code_id in _interactive_cache:
entry = _interactive_cache[code_id]
if len(entry) != 1:
return _interactive_cache[code_id][2]
return []


def checkcache(filename=None):
"""Discard cache entries that are out of date.
(This is not checked upon each call!)"""

if filename is None:
filenames = list(cache.keys())
elif filename in cache:
filenames = [filename]
# get keys atomically
filenames = cache.copy().keys()
else:
return
filenames = [filename]

for filename in filenames:
entry = cache[filename]
try:
entry = cache[filename]
except KeyError:
continue

if len(entry) == 1:
# lazy cache entry, leave it lazy.
continue
size, mtime, lines, fullname = entry
if mtime is None:
continue # no-op for files loaded via a __loader__
try:
# This import can fail if the interpreter is shutting down
import os
except ImportError:
return
try:
stat = os.stat(fullname)
except OSError:
except (OSError, ValueError):
cache.pop(filename, None)
continue
if size != stat.st_size or mtime != stat.st_mtime:
Expand All @@ -82,6 +104,17 @@ def updatecache(filename, module_globals=None):
If something's wrong, print a message, discard the cache entry,
and return an empty list."""

# These imports are not at top level because linecache is in the critical
# path of the interpreter startup and importing os and sys take a lot of time
# and slows down the startup sequence.
try:
import os
import sys
import tokenize
except ImportError:
# These import can fail if the interpreter is shutting down
return []

if filename in cache:
if len(cache[filename]) != 1:
cache.pop(filename, None)
Expand Down Expand Up @@ -128,16 +161,20 @@ def updatecache(filename, module_globals=None):
try:
stat = os.stat(fullname)
break
except OSError:
except (OSError, ValueError):
pass
else:
return []
except ValueError: # may be raised by os.stat()
return []
try:
with tokenize.open(fullname) as fp:
lines = fp.readlines()
except (OSError, UnicodeDecodeError, SyntaxError):
return []
if lines and not lines[-1].endswith('\n'):
if not lines:
lines = ['\n']
elif not lines[-1].endswith('\n'):
lines[-1] += '\n'
size, mtime = stat.st_size, stat.st_mtime
cache[filename] = size, mtime, lines, fullname
Expand Down Expand Up @@ -166,17 +203,29 @@ def lazycache(filename, module_globals):
return False
# Try for a __loader__, if available
if module_globals and '__name__' in module_globals:
name = module_globals['__name__']
if (loader := module_globals.get('__loader__')) is None:
if spec := module_globals.get('__spec__'):
try:
loader = spec.loader
except AttributeError:
pass
spec = module_globals.get('__spec__')
name = getattr(spec, 'name', None) or module_globals['__name__']
loader = getattr(spec, 'loader', None)
if loader is None:
loader = module_globals.get('__loader__')
get_source = getattr(loader, 'get_source', None)

if name and get_source:
get_lines = functools.partial(get_source, name)
def get_lines(name=name, *args, **kwargs):
return get_source(name, *args, **kwargs)
cache[filename] = (get_lines,)
return True
return False

def _register_code(code, string, name):
entry = (len(string),
None,
[line + '\n' for line in string.splitlines()],
name)
stack = [code]
while stack:
code = stack.pop()
for const in code.co_consts:
if isinstance(const, type(code)):
stack.append(const)
_interactive_cache[_make_key(code)] = entry
3 changes: 3 additions & 0 deletions Lib/pprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
sort_dicts
If true, dict keys are sorted.

underscore_numbers
If true, digit groups are separated with underscores.

"""
indent = int(indent)
width = int(width)
Expand Down
60 changes: 59 additions & 1 deletion Lib/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
except ImportError:
SimpleQueue = None

__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue', 'SimpleQueue']
__all__ = [
'Empty',
'Full',
'ShutDown',
'Queue',
'PriorityQueue',
'LifoQueue',
'SimpleQueue',
]


try:
Expand All @@ -25,6 +33,10 @@ class Full(Exception):
pass


class ShutDown(Exception):
'''Raised when put/get with shut-down queue.'''


class Queue:
'''Create a queue object with a given maximum size.

Expand Down Expand Up @@ -54,6 +66,9 @@ def __init__(self, maxsize=0):
self.all_tasks_done = threading.Condition(self.mutex)
self.unfinished_tasks = 0

# Queue shutdown state
self.is_shutdown = False

def task_done(self):
'''Indicate that a formerly enqueued task is complete.

Expand All @@ -65,6 +80,9 @@ def task_done(self):
have been processed (meaning that a task_done() call was received
for every item that had been put() into the queue).

shutdown(immediate=True) calls task_done() for each remaining item in
the queue.

Raises a ValueError if called more times than there were items
placed in the queue.
'''
Expand Down Expand Up @@ -129,15 +147,21 @@ def put(self, item, block=True, timeout=None):
Otherwise ('block' is false), put an item on the queue if a free slot
is immediately available, else raise the Full exception ('timeout'
is ignored in that case).

Raises ShutDown if the queue has been shut down.
'''
with self.not_full:
if self.is_shutdown:
raise ShutDown
if self.maxsize > 0:
if not block:
if self._qsize() >= self.maxsize:
raise Full
elif timeout is None:
while self._qsize() >= self.maxsize:
self.not_full.wait()
if self.is_shutdown:
raise ShutDown
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
Expand All @@ -147,6 +171,8 @@ def put(self, item, block=True, timeout=None):
if remaining <= 0.0:
raise Full
self.not_full.wait(remaining)
if self.is_shutdown:
raise ShutDown
self._put(item)
self.unfinished_tasks += 1
self.not_empty.notify()
Expand All @@ -161,14 +187,21 @@ def get(self, block=True, timeout=None):
Otherwise ('block' is false), return an item if one is immediately
available, else raise the Empty exception ('timeout' is ignored
in that case).

Raises ShutDown if the queue has been shut down and is empty,
or if the queue has been shut down immediately.
'''
with self.not_empty:
if self.is_shutdown and not self._qsize():
raise ShutDown
if not block:
if not self._qsize():
raise Empty
elif timeout is None:
while not self._qsize():
self.not_empty.wait()
if self.is_shutdown and not self._qsize():
raise ShutDown
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
Expand All @@ -178,6 +211,8 @@ def get(self, block=True, timeout=None):
if remaining <= 0.0:
raise Empty
self.not_empty.wait(remaining)
if self.is_shutdown and not self._qsize():
raise ShutDown
item = self._get()
self.not_full.notify()
return item
Expand All @@ -198,6 +233,29 @@ def get_nowait(self):
'''
return self.get(block=False)

def shutdown(self, immediate=False):
'''Shut-down the queue, making queue gets and puts raise ShutDown.

By default, gets will only raise once the queue is empty. Set
'immediate' to True to make gets raise immediately instead.

All blocked callers of put() and get() will be unblocked. If
'immediate', a task is marked as done for each item remaining in
the queue, which may unblock callers of join().
'''
with self.mutex:
self.is_shutdown = True
if immediate:
while self._qsize():
self._get()
if self.unfinished_tasks > 0:
self.unfinished_tasks -= 1
# release all blocked threads in `join()`
self.all_tasks_done.notify_all()
# All getters need to re-check queue-empty to raise ShutDown
self.not_empty.notify_all()
self.not_full.notify_all()

# Override these methods to implement other queue organizations
# (e.g. stack or priority queue).
# These will only be called with appropriate locks held
Expand Down
2 changes: 1 addition & 1 deletion Lib/sched.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
implement simulated time by writing your own functions. This can
also be used to integrate scheduling with STDWIN events; the delay
function is allowed to modify the queue. Time can be expressed as
integers or floating point numbers, as long as it is consistent.
integers or floating-point numbers, as long as it is consistent.

Events are specified by tuples (time, priority, action, argument, kwargs).
As in UNIX, lower priority numbers mean higher priority; in this
Expand Down
1 change: 0 additions & 1 deletion Lib/test/test_heapq.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import unittest
import doctest

from test import support
from test.support import import_helper
from unittest import TestCase, skipUnless
from operator import itemgetter
Expand Down
Loading
Loading