Skip to content

Commit

Permalink
Migrate patch to v3.13.
Browse files Browse the repository at this point in the history
  • Loading branch information
freakboy3742 committed Oct 18, 2023
1 parent ad056f0 commit a1c7f22
Show file tree
Hide file tree
Showing 41 changed files with 864 additions and 104 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Modules/Setup.stdlib
Modules/config.c
Modules/ld_so_aix
Programs/_freeze_module
Programs/_freeze_importlib
Programs/_testembed
PC/python_nt*.h
PC/pythonnt_rc*.h
Expand Down Expand Up @@ -144,6 +145,13 @@ Tools/msi/obj
Tools/ssl/amd64
Tools/ssl/win32
Tools/freeze/test/outdir
Tools/iOS-testbed/build
Tools/iOS-testbed/iOS Testbed.xcodeproj/project.xcworkspace/xcuserdata
Tools/iOS-testbed/iOS Testbed.xcodeproj/project.xcworkspace/xcshareddata
Tools/iOS-testbed/iOS Testbed.xcodeproj/xcuserdata
Tools/iOS-testbed/iOS Testbed.xcodeproj/xcshareddata
Tools/iOS-testbed/Support/python-stdlib
Tools/iOS-testbed/Support/Python.xcframework

# The frozen modules are always generated by the build so we don't
# keep them in the repo. Also see Tools/build/freeze_modules.py.
Expand Down
8 changes: 8 additions & 0 deletions Include/internal/pycore_faulthandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ extern "C" {
# include <signal.h> // sigaction
#endif

#ifdef __APPLE__
# include "TargetConditionals.h"
#endif /* __APPLE__ */

// tvOS and watchOS don't provide a number of important POSIX functions.
#if TARGET_OS_TV || TARGET_OS_WATCH
# undef HAVE_SIGALTSTACK
#endif /* TVOS || WATCHOS */

#ifndef MS_WINDOWS
/* register() is useless on Windows, because only SIGSEGV, SIGABRT and
Expand Down
36 changes: 36 additions & 0 deletions Lib/_ios_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from ctypes import cdll, c_void_p, c_char_p
from ctypes import util


def get_platform_ios():
objc = cdll.LoadLibrary(util.find_library(b'objc'))

objc.objc_getClass.restype = c_void_p
objc.objc_getClass.argtypes = [c_char_p]
objc.objc_msgSend.restype = c_void_p
objc.objc_msgSend.argtypes = [c_void_p, c_void_p]
objc.sel_registerName.restype = c_void_p
objc.sel_registerName.argtypes = [c_char_p]

UIDevice = c_void_p(objc.objc_getClass(b'UIDevice'))
SEL_currentDevice = c_void_p(objc.sel_registerName(b'currentDevice'))
device = c_void_p(objc.objc_msgSend(UIDevice, SEL_currentDevice))

SEL_systemVersion = c_void_p(objc.sel_registerName(b'systemVersion'))
systemVersion = c_void_p(objc.objc_msgSend(device, SEL_systemVersion))

SEL_systemName = c_void_p(objc.sel_registerName(b'systemName'))
systemName = c_void_p(objc.objc_msgSend(device, SEL_systemName))

SEL_model = c_void_p(objc.sel_registerName(b'model'))
systemModel = c_void_p(objc.objc_msgSend(device, SEL_model))

# UTF8String returns a const char*;
SEL_UTF8String = c_void_p(objc.sel_registerName(b'UTF8String'))
objc.objc_msgSend.restype = c_char_p

system = objc.objc_msgSend(systemName, SEL_UTF8String).decode()
release = objc.objc_msgSend(systemVersion, SEL_UTF8String).decode()
model = objc.objc_msgSend(systemModel, SEL_UTF8String).decode()

return system, release, model
2 changes: 1 addition & 1 deletion Lib/ctypes/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def find_library(name):
return fname
return None

elif os.name == "posix" and sys.platform == "darwin":
elif os.name == "posix" and sys.platform in {'darwin', 'ios', 'tvos', 'watchos'}:
from ctypes.macholib.dyld import dyld_find as _dyld_find
def find_library(name):
possible = ['lib%s.dylib' % name,
Expand Down
59 changes: 58 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

# Bootstrap-related code ######################################################
_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin'
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'watchos'
_CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
+ _CASE_INSENSITIVE_PLATFORMS_STR_KEY)

Expand Down Expand Up @@ -1704,6 +1704,59 @@ def __repr__(self):
return f'FileFinder({self.path!r})'


class AppleFrameworkLoader(ExtensionFileLoader):
"""A loader for modules that have been packaged as Apple Frameworks for
compatibility with Apple's App Store policies.
For compatibility with the App Store, *all* binary modules must be in .dylibs,
contained in a Framework, in the ``Frameworks`` folder of the packaged app. If
you're trying to run "from foo import _bar", and _bar is implemented with the binary
module "foo/_bar.abi3.dylib" (or any other .dylib extension), this loader will look
for "{sys.executable}/Frameworks/foo__bar.framework/_bar.abi3.dylib" (forming the
package name by taking the full path of the library, and replacing ``/`` with
``_``). The app packaging tool is responsible for putting the library in this
location.
However, the ``__file__`` attribute of the _bar module will report as the original
location inside the ``foo`` directory. This so that code that depends on walking
directory trees will continue to work as expected based on the *original* file
location.
"""
def __init__(self, fullname, dylib_file, path):
super().__init__(fullname, dylib_file)
self.parent_paths = path

def create_module(self, spec):
mod = super().create_module(spec)
if self.parent_paths:
for parent_path in self.parent_paths:
if _path_isdir(parent_path):
mod.__file__ = _path_join(parent_path, _path_split(self.path)[-1])
continue
return mod


class AppleFrameworkFinder:
"""A finder for modules that have been packaged as Apple Frameworks
for compatibility with Apple's App Store policies.
See AppleFrameworkLoader for details.
"""
def __init__(self, path):
self.frameworks_path = path

def find_spec(self, fullname, path, target=None):
name = fullname.split(".")[-1]

for extension in EXTENSION_SUFFIXES:
dylib_file = _path_join(self.frameworks_path, f"{fullname}.framework", f"{name}{extension}")
_bootstrap._verbose_message('Looking for Apple Framework dylib {}', dylib_file)
if _path_isfile(dylib_file):
loader = AppleFrameworkLoader(fullname, dylib_file, path)
return _bootstrap.spec_from_loader(fullname, loader)

return None

# Import setup ###############################################################

def _fix_up_module(ns, name, pathname, cpathname=None):
Expand Down Expand Up @@ -1753,3 +1806,7 @@ def _install(_bootstrap_module):
supported_loaders = _get_supported_file_loaders()
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
sys.meta_path.append(PathFinder)
if sys.platform in {"ios", "tvos", "watchos"}:
frameworks_folder = _path_join(_path_split(sys.executable)[0], "Frameworks")
_bootstrap._verbose_message('Adding Apple Framework dylib finder at {}', frameworks_folder)
sys.meta_path.append(AppleFrameworkFinder(frameworks_folder))
61 changes: 55 additions & 6 deletions Lib/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,26 @@ def mac_ver(release='', versioninfo=('', '', ''), machine=''):
# If that also doesn't work return the default values
return release, versioninfo, machine

def iOS_ver():
"""Get iOS/tvOS version information, and return it as a
tuple (system, release, model). All tuple entries are strings.
"""
import _ios_support
return _ios_support.get_platform_ios()

def is_simulator():
"""Determine if the current platform is a device simulator.
Only useful when working with iOS, tvOS or watchOS, because
Apple provides simulator platforms for those devices.
If the platform is actual hardware, returns False. Will also
return False for device *emulators*, which are indistinguishable
from actual devices because they are reproducing actual device
properties.
"""
return getattr(sys.implementation, "_simulator", False)

def _java_getprop(name, default):

from java.lang import System
Expand Down Expand Up @@ -652,7 +672,7 @@ def _syscmd_file(target, default=''):
default in case the command should fail.
"""
if sys.platform in ('dos', 'win32', 'win16'):
if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos'}:
# XXX Others too ?
return default

Expand Down Expand Up @@ -814,6 +834,24 @@ def get_OpenVMS():
csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
return 'Alpha' if cpu_number >= 128 else 'VAX'

# On iOS, tvOS and watchOS, os.uname returns the architecture
# as uname.machine. On device it doesn't; but there's only
# on CPU architecture on device
def get_ios():
if getattr(sys.implementation, "_simulator", False):
return os.uname().machine
return 'arm64'

def get_tvos():
if getattr(sys.implementation, "_simulator", False):
return os.uname().machine
return 'arm64'

def get_watchos():
if getattr(sys.implementation, "_simulator", False):
return os.uname().machine
return 'arm64_32'

def from_subprocess():
"""
Fall back to `uname -p`
Expand Down Expand Up @@ -968,6 +1006,15 @@ def uname():
system = 'Windows'
release = 'Vista'

# Normalize responses on Apple mobile platforms
if sys.platform in {'ios', 'tvos'}:
system, release, model = iOS_ver()

# On iOS/tvOS simulators, os.uname() reports the machine as something
# like "arm64" or "x86_64".
if getattr(sys.implementation, "_simulator", False):
machine = f'{model}Simulator'

vals = system, node, release, version, machine
# Replace 'unknown' values with the more portable ''
_uname_cache = uname_result(*map(_unknown_as_blank, vals))
Expand Down Expand Up @@ -1247,11 +1294,13 @@ def platform(aliased=False, terse=False):
system, release, version = system_alias(system, release, version)

if system == 'Darwin':
# macOS (darwin kernel)
macos_release = mac_ver()[0]
if macos_release:
system = 'macOS'
release = macos_release
if sys.platform in {'ios', 'tvos'}:
system, release, _ = iOS_ver()
else:
macos_release = mac_ver()[0]
if macos_release:
system = 'macOS'
release = macos_release

if system == 'Windows':
# MS platforms
Expand Down
3 changes: 3 additions & 0 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ def _get_path(userbase):

if sys.platform == 'darwin' and sys._framework:
return f'{userbase}/lib/python/site-packages'
elif sys.platform in ('ios', 'tvos', 'watchos'):
from sysconfig import get_path
return get_path('purelib', sys.platform)

return f'{userbase}/lib/python{version[0]}.{version[1]}/site-packages'

Expand Down
48 changes: 24 additions & 24 deletions Lib/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
else:
_mswindows = True

# wasm32-emscripten and wasm32-wasi do not support processes
_can_fork_exec = sys.platform not in {"emscripten", "wasi"}
# some platforms do not support processes
_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"}

if _mswindows:
import _winapi
Expand Down Expand Up @@ -103,18 +103,22 @@
if _can_fork_exec:
from _posixsubprocess import fork_exec as _fork_exec
# used in methods that are called by __del__
_waitpid = os.waitpid
_waitstatus_to_exitcode = os.waitstatus_to_exitcode
_WIFSTOPPED = os.WIFSTOPPED
_WSTOPSIG = os.WSTOPSIG
_WNOHANG = os.WNOHANG
class _del_safe:
waitpid = os.waitpid
waitstatus_to_exitcode = os.waitstatus_to_exitcode
WIFSTOPPED = os.WIFSTOPPED
WSTOPSIG = os.WSTOPSIG
WNOHANG = os.WNOHANG
ECHILD = errno.ECHILD
else:
_fork_exec = None
_waitpid = None
_waitstatus_to_exitcode = None
_WIFSTOPPED = None
_WSTOPSIG = None
_WNOHANG = None
class _del_safe:
waitpid = None
waitstatus_to_exitcode = None
WIFSTOPPED = None
WSTOPSIG = None
WNOHANG = None
ECHILD = errno.ECHILD

import select
import selectors

Expand Down Expand Up @@ -1951,20 +1955,16 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
raise child_exception_type(err_msg)


def _handle_exitstatus(self, sts,
_waitstatus_to_exitcode=_waitstatus_to_exitcode,
_WIFSTOPPED=_WIFSTOPPED,
_WSTOPSIG=_WSTOPSIG):
def _handle_exitstatus(self, sts, _del_safe=_del_safe):
"""All callers to this function MUST hold self._waitpid_lock."""
# This method is called (indirectly) by __del__, so it cannot
# refer to anything outside of its local scope.
if _WIFSTOPPED(sts):
self.returncode = -_WSTOPSIG(sts)
if _del_safe.WIFSTOPPED(sts):
self.returncode = -_del_safe.WSTOPSIG(sts)
else:
self.returncode = _waitstatus_to_exitcode(sts)
self.returncode = _del_safe.waitstatus_to_exitcode(sts)

def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
_WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD):
def _internal_poll(self, _deadstate=None, _del_safe=_del_safe):
"""Check if child process has terminated. Returns returncode
attribute.
Expand All @@ -1980,13 +1980,13 @@ def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
try:
if self.returncode is not None:
return self.returncode # Another thread waited.
pid, sts = _waitpid(self.pid, _WNOHANG)
pid, sts = _del_safe.waitpid(self.pid, _del_safe.WNOHANG)
if pid == self.pid:
self._handle_exitstatus(sts)
except OSError as e:
if _deadstate is not None:
self.returncode = _deadstate
elif e.errno == _ECHILD:
elif e.errno == _del_safe.ECHILD:
# This happens if SIGCLD is set to be ignored or
# waiting for child processes has otherwise been
# disabled for our process. This child is dead, we
Expand Down
Loading

0 comments on commit a1c7f22

Please sign in to comment.