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
8 changes: 4 additions & 4 deletions .github/workflows/CI_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ jobs:
if: matrix.build_configuration == 'Release'
working-directory: installer
run: |
$env:PYTHONBUILDDIR_ARM64='${{ github.workspace }}\packages\pythonarm64.3.14.3\tools'
$env:PYTHONBUILDDIR_X64='${{ github.workspace }}\packages\python.3.14.3\tools'
$env:PYTHONBUILDDIR='${{ github.workspace }}\packages\pythonx86.3.14.3\tools'
$env:PYTHONBUILDDIR_ARM64='${{ github.workspace }}\packages\pythonarm64.3.14.4\tools'
$env:PYTHONBUILDDIR_X64='${{ github.workspace }}\packages\python.3.14.4\tools'
$env:PYTHONBUILDDIR='${{ github.workspace }}\packages\pythonx86.3.14.4\tools'
Rename-Item -Path ".\buildPaths.bat.orig" -NewName "buildPaths.bat"
dotnet tool install --global wix --version 6.0.2
dotnet tool install --global wix --version 7.0.0
.\buildAll.bat ${{ matrix.build_platform }}
10 changes: 5 additions & 5 deletions PythonLib/full/_py_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,18 +647,18 @@ def __enter__(self):
context = None
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._showwarning = self._module.showwarning
self._showwarnmsg_impl = self._module._showwarnmsg_impl
self._showwarning = self._module.showwarning
self._module._filters_mutated_lock_held()
if self._record:
if _use_context:
context.log = log = []
else:
log = []
self._module._showwarnmsg_impl = log.append
# Reset showwarning() to the default implementation to make sure
# that _showwarnmsg() calls _showwarnmsg_impl()
self._module.showwarning = self._module._showwarning_orig
# Reset showwarning() to the default implementation to make sure
# that _showwarnmsg() calls _showwarnmsg_impl()
self._module.showwarning = self._module._showwarning_orig
else:
log = None
if self._filter is not None:
Expand All @@ -673,8 +673,8 @@ def __exit__(self, *exc_info):
self._module._warnings_context.set(self._saved_context)
else:
self._module.filters = self._filters
self._module.showwarning = self._showwarning
self._module._showwarnmsg_impl = self._showwarnmsg_impl
self._module.showwarning = self._showwarning
self._module._filters_mutated_lock_held()


Expand Down
17 changes: 6 additions & 11 deletions PythonLib/full/_pyrepl/windows_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,18 +283,13 @@ def __write_changed_line(
self._erase_to_end()

self.__write(newline[x_pos:])
if wlen(newline) == self.width:
# If we wrapped we want to start at the next line
self._move_relative(0, y + 1)
self.posxy = 0, y + 1
else:
self.posxy = wlen(newline), y
self.posxy = min(wlen(newline), self.width - 1), y

if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
# ANSI escape characters are present, so we can't assume
# anything about the position of the cursor. Moving the cursor
# to the left margin should work to get to a known position.
self.move_cursor(0, y)
if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
# ANSI escape characters are present, so we can't assume
# anything about the position of the cursor. Moving the cursor
# to the left margin should work to get to a known position.
self.move_cursor(0, y)

def _scroll(
self, top: int, bottom: int, left: int | None = None, right: int | None = None
Expand Down
19 changes: 16 additions & 3 deletions PythonLib/full/annotationlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,7 @@ def get_annotations(
does not exist, the __annotate__ function is called. The
FORWARDREF format uses __annotations__ if it exists and can be
evaluated, and otherwise falls back to calling the __annotate__ function.
The SOURCE format tries __annotate__ first, and falls back to
The STRING format tries __annotate__ first, and falls back to
using __annotations__, stringified using annotations_to_string().

This function handles several details for you:
Expand Down Expand Up @@ -1037,13 +1037,26 @@ def get_annotations(
obj_globals = obj_locals = unwrap = None

if unwrap is not None:
# Use an id-based visited set to detect cycles in the __wrapped__
# and functools.partial.func chain (e.g. f.__wrapped__ = f).
# On cycle detection we stop and use whatever __globals__ we have
# found so far, mirroring the approach of inspect.unwrap().
_seen_ids = {id(unwrap)}
while True:
if hasattr(unwrap, "__wrapped__"):
unwrap = unwrap.__wrapped__
candidate = unwrap.__wrapped__
if id(candidate) in _seen_ids:
break
_seen_ids.add(id(candidate))
unwrap = candidate
continue
if functools := sys.modules.get("functools"):
if isinstance(unwrap, functools.partial):
unwrap = unwrap.func
candidate = unwrap.func
if id(candidate) in _seen_ids:
break
_seen_ids.add(id(candidate))
unwrap = candidate
continue
break
if hasattr(unwrap, "__globals__"):
Expand Down
10 changes: 6 additions & 4 deletions PythonLib/full/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ def _copy_items(items):
return copy.copy(items)


def _identity(value):
return value


# ===============
# Formatting Help
# ===============
Expand Down Expand Up @@ -200,7 +204,7 @@ def _set_color(self, color):
self._decolor = decolor
else:
self._theme = get_theme(force_no_color=True).argparse
self._decolor = lambda text: text
self._decolor = _identity

# ===============================
# Section and indentation methods
Expand Down Expand Up @@ -1903,9 +1907,7 @@ def __init__(self,
self._subparsers = None

# register types
def identity(string):
return string
self.register('type', None, identity)
self.register('type', None, _identity)

# add help argument if necessary
# (using explicit default to override global argument_default)
Expand Down
11 changes: 11 additions & 0 deletions PythonLib/full/asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,17 @@ async def start_tls(self, transport, protocol, sslcontext, *,
# have a chance to get called before "ssl_protocol.connection_made()".
transport.pause_reading()

# gh-142352: move buffered StreamReader data to SSLProtocol
if server_side:
from .streams import StreamReaderProtocol
if isinstance(protocol, StreamReaderProtocol):
stream_reader = getattr(protocol, '_stream_reader', None)
if stream_reader is not None:
buffer = stream_reader._buffer
if buffer:
ssl_protocol._incoming.write(buffer)
buffer.clear()

transport.set_protocol(ssl_protocol)
conmade_cb = self.call_soon(ssl_protocol.connection_made, transport)
resume_cb = self.call_soon(transport.resume_reading)
Expand Down
4 changes: 2 additions & 2 deletions PythonLib/full/asyncio/base_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def _try_finish(self):
# to avoid hanging forever in self._wait as otherwise _exit_waiters
# would never be woken up, we wake them up here.
for waiter in self._exit_waiters:
if not waiter.cancelled():
if not waiter.done():
waiter.set_result(self._returncode)
if all(p is not None and p.disconnected
for p in self._pipes.values()):
Expand All @@ -278,7 +278,7 @@ def _call_connection_lost(self, exc):
finally:
# wake up futures waiting for wait()
for waiter in self._exit_waiters:
if not waiter.cancelled():
if not waiter.done():
waiter.set_result(self._returncode)
self._exit_waiters = None
self._loop = None
Expand Down
2 changes: 1 addition & 1 deletion PythonLib/full/asyncio/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Queue(mixins._LoopBoundMixin):
is an integer greater than 0, then "await put()" will block when the
queue reaches maxsize, until an item is removed by get().

Unlike the standard library Queue, you can reliably know this Queue's size
Unlike queue.Queue, you can reliably know this Queue's size
with qsize(), since your single-threaded asyncio application won't be
interrupted between calling qsize() and doing an operation on the Queue.
"""
Expand Down
23 changes: 15 additions & 8 deletions PythonLib/full/asyncio/windows_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import msvcrt
import os
import subprocess
import tempfile
import warnings


Expand All @@ -24,17 +23,14 @@
PIPE = subprocess.PIPE
STDOUT = subprocess.STDOUT
_mmap_counter = itertools.count()
_MAX_PIPE_ATTEMPTS = 20


# Replacement for os.pipe() using handles instead of fds


def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):
"""Like os.pipe() but with overlapped support and using handles not fds."""
address = tempfile.mktemp(
prefix=r'\\.\pipe\python-pipe-{:d}-{:d}-'.format(
os.getpid(), next(_mmap_counter)))

if duplex:
openmode = _winapi.PIPE_ACCESS_DUPLEX
access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
Expand All @@ -56,9 +52,20 @@ def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):

h1 = h2 = None
try:
h1 = _winapi.CreateNamedPipe(
address, openmode, _winapi.PIPE_WAIT,
1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
for attempts in itertools.count():
address = r'\\.\pipe\python-pipe-{:d}-{:d}-{}'.format(
os.getpid(), next(_mmap_counter), os.urandom(8).hex())
try:
h1 = _winapi.CreateNamedPipe(
address, openmode, _winapi.PIPE_WAIT,
1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
break
except OSError as e:
if attempts >= _MAX_PIPE_ATTEMPTS:
raise
if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
_winapi.ERROR_ACCESS_DENIED):
raise

h2 = _winapi.CreateFile(
address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING,
Expand Down
2 changes: 2 additions & 0 deletions PythonLib/full/ctypes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ def _load_library(self, name, mode, handle, winmode):
if name and name.endswith(")") and ".a(" in name:
mode |= _os.RTLD_MEMBER | _os.RTLD_NOW
self._name = name
if handle is not None:
return handle
return _dlopen(name, mode)

def __repr__(self):
Expand Down
26 changes: 16 additions & 10 deletions PythonLib/full/ctypes/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,30 @@ def find_library(name):
wintypes.DWORD,
)

_psapi = ctypes.WinDLL('psapi', use_last_error=True)
_enum_process_modules = _psapi["EnumProcessModules"]
_enum_process_modules.restype = wintypes.BOOL
_enum_process_modules.argtypes = (
wintypes.HANDLE,
ctypes.POINTER(wintypes.HMODULE),
wintypes.DWORD,
wintypes.LPDWORD,
)
# gh-145307: We defer loading psapi.dll until _get_module_handles is called.
# Loading additional DLLs at startup for functionality that may never be
# used is wasteful.
_enum_process_modules = None

def _get_module_filename(module: wintypes.HMODULE):
name = (wintypes.WCHAR * 32767)() # UNICODE_STRING_MAX_CHARS
if _k32_get_module_file_name(module, name, len(name)):
return name.value
return None


def _get_module_handles():
global _enum_process_modules
if _enum_process_modules is None:
_psapi = ctypes.WinDLL('psapi', use_last_error=True)
_enum_process_modules = _psapi["EnumProcessModules"]
_enum_process_modules.restype = wintypes.BOOL
_enum_process_modules.argtypes = (
wintypes.HANDLE,
ctypes.POINTER(wintypes.HMODULE),
wintypes.DWORD,
wintypes.LPDWORD,
)

process = _get_current_process()
space_needed = wintypes.DWORD()
n = 1024
Expand Down
Loading