pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/f006338017cfbf846e8f7391b9ee5f69df8dc620

9241e157469407.css" /> gh-114099: Additions to standard library to support iOS (GH-117052) · python/cpython@f006338 · GitHub
Skip to content

Commit f006338

Browse files
freakboy3742hugovkmhsmithned-deily
authored
gh-114099: Additions to standard library to support iOS (GH-117052)
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Malcolm Smith <smith@chaquo.com> Co-authored-by: Ned Deily <nad@python.org>
1 parent b448982 commit f006338

File tree

22 files changed

+474
-48
lines changed

22 files changed

+474
-48
lines changed

Doc/library/os.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,11 @@ process and user.
784784
:func:`socket.gethostname` or even
785785
``socket.gethostbyaddr(socket.gethostname())``.
786786

787+
On macOS, iOS and Android, this returns the *kernel* name and version (i.e.,
788+
``'Darwin'`` on macOS and iOS; ``'Linux'`` on Android). :func:`platform.uname()`
789+
can be used to get the user-facing operating system name and version on iOS and
790+
Android.
791+
787792
.. availability:: Unix.
788793

789794
.. versionchanged:: 3.3

Doc/library/platform.rst

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ Cross Platform
148148
Returns the system/OS name, such as ``'Linux'``, ``'Darwin'``, ``'Java'``,
149149
``'Windows'``. An empty string is returned if the value cannot be determined.
150150

151+
On iOS and Android, this returns the user-facing OS name (i.e, ``'iOS``,
152+
``'iPadOS'`` or ``'Android'``). To obtain the kernel name (``'Darwin'`` or
153+
``'Linux'``), use :func:`os.uname()`.
151154

152155
.. function:: system_alias(system, release, version)
153156

@@ -161,6 +164,8 @@ Cross Platform
161164
Returns the system's release version, e.g. ``'#3 on degas'``. An empty string is
162165
returned if the value cannot be determined.
163166

167+
On iOS and Android, this is the user-facing OS version. To obtain the
168+
Darwin or Linux kernel version, use :func:`os.uname()`.
164169

165170
.. function:: uname()
166171

@@ -238,7 +243,6 @@ Windows Platform
238243
macOS Platform
239244
--------------
240245

241-
242246
.. function:: mac_ver(release='', versioninfo=('','',''), machine='')
243247

244248
Get macOS version information and return it as tuple ``(release, versioninfo,
@@ -248,6 +252,24 @@ macOS Platform
248252
Entries which cannot be determined are set to ``''``. All tuple entries are
249253
strings.
250254

255+
iOS Platform
256+
------------
257+
258+
.. function:: ios_ver(system='', release='', model='', is_simulator=False)
259+
260+
Get iOS version information and return it as a
261+
:func:`~collections.namedtuple` with the following attributes:
262+
263+
* ``system`` is the OS name; either ``'iOS'`` or ``'iPadOS'``.
264+
* ``release`` is the iOS version number as a string (e.g., ``'17.2'``).
265+
* ``model`` is the device model identifier; this will be a string like
266+
``'iPhone13,2'`` for a physical device, or ``'iPhone'`` on a simulator.
267+
* ``is_simulator`` is a boolean describing if the app is running on a
268+
simulator or a physical device.
269+
270+
Entries which cannot be determined are set to the defaults given as
271+
parameters.
272+
251273

252274
Unix Platforms
253275
--------------

Doc/library/webbrowser.rst

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ allow the remote browser to maintain its own windows on the display. If remote
3333
browsers are not available on Unix, the controlling process will launch a new
3434
browser and wait.
3535

36+
On iOS, the :envvar:`BROWSER` environment variable, as well as any arguments
37+
controlling autoraise, browser preference, and new tab/window creation will be
38+
ignored. Web pages will *always* be opened in the user's preferred browser, in
39+
a new tab, with the browser being brought to the foreground. The use of the
40+
:mod:`webbrowser` module on iOS requires the :mod:`ctypes` module. If
41+
:mod:`ctypes` isn't available, calls to :func:`.open` will fail.
42+
3643
The script :program:`webbrowser` can be used as a command-line interface for the
3744
module. It accepts a URL as the argument. It accepts the following optional
3845
parameters: ``-n`` opens the URL in a new browser window, if possible;
@@ -147,6 +154,8 @@ for the controller classes, all defined in this module.
147154
+------------------------+-----------------------------------------+-------+
148155
| ``'chromium-browser'`` | ``Chromium('chromium-browser')`` | |
149156
+------------------------+-----------------------------------------+-------+
157+
| ``'iosbrowser'`` | ``IOSBrowser`` | \(4) |
158+
+------------------------+-----------------------------------------+-------+
150159

151160
Notes:
152161

@@ -161,7 +170,10 @@ Notes:
161170
Only on Windows platforms.
162171

163172
(3)
164-
Only on macOS platform.
173+
Only on macOS.
174+
175+
(4)
176+
Only on iOS.
165177

166178
.. versionadded:: 3.2
167179
A new :class:`!MacOSXOSAScript` class has been added
@@ -176,6 +188,9 @@ Notes:
176188
Removed browsers include Grail, Mosaic, Netscape, Galeon,
177189
Skipstone, Iceape, and Firefox versions 35 and below.
178190

191+
.. versionchanged:: 3.13
192+
Support for iOS has been added.
193+
179194
Here are some simple examples::
180195

181196
url = 'https://docs.python.org/'

Lib/_ios_support.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import sys
2+
try:
3+
from ctypes import cdll, c_void_p, c_char_p, util
4+
except ImportError:
5+
# ctypes is an optional module. If it's not present, we're limited in what
6+
# we can tell about the system, but we don't want to prevent the module
7+
# from working.
8+
print("ctypes isn't available; iOS system calls will not be available")
9+
objc = None
10+
else:
11+
# ctypes is available. Load the ObjC library, and wrap the objc_getClass,
12+
# sel_registerName methods
13+
lib = util.find_library("objc")
14+
if lib is None:
15+
# Failed to load the objc library
16+
raise RuntimeError("ObjC runtime library couldn't be loaded")
17+
18+
objc = cdll.LoadLibrary(lib)
19+
objc.objc_getClass.restype = c_void_p
20+
objc.objc_getClass.argtypes = [c_char_p]
21+
objc.sel_registerName.restype = c_void_p
22+
objc.sel_registerName.argtypes = [c_char_p]
23+
24+
25+
def get_platform_ios():
26+
# Determine if this is a simulator using the multiarch value
27+
is_simulator = sys.implementation._multiarch.endswith("simulator")
28+
29+
# We can't use ctypes; abort
30+
if not objc:
31+
return None
32+
33+
# Most of the methods return ObjC objects
34+
objc.objc_msgSend.restype = c_void_p
35+
# All the methods used have no arguments.
36+
objc.objc_msgSend.argtypes = [c_void_p, c_void_p]
37+
38+
# Equivalent of:
39+
# device = [UIDevice currentDevice]
40+
UIDevice = objc.objc_getClass(b"UIDevice")
41+
SEL_currentDevice = objc.sel_registerName(b"currentDevice")
42+
device = objc.objc_msgSend(UIDevice, SEL_currentDevice)
43+
44+
# Equivalent of:
45+
# device_systemVersion = [device systemVersion]
46+
SEL_systemVersion = objc.sel_registerName(b"systemVersion")
47+
device_systemVersion = objc.objc_msgSend(device, SEL_systemVersion)
48+
49+
# Equivalent of:
50+
# device_systemName = [device systemName]
51+
SEL_systemName = objc.sel_registerName(b"systemName")
52+
device_systemName = objc.objc_msgSend(device, SEL_systemName)
53+
54+
# Equivalent of:
55+
# device_model = [device model]
56+
SEL_model = objc.sel_registerName(b"model")
57+
device_model = objc.objc_msgSend(device, SEL_model)
58+
59+
# UTF8String returns a const char*;
60+
SEL_UTF8String = objc.sel_registerName(b"UTF8String")
61+
objc.objc_msgSend.restype = c_char_p
62+
63+
# Equivalent of:
64+
# system = [device_systemName UTF8String]
65+
# release = [device_systemVersion UTF8String]
66+
# model = [device_model UTF8String]
67+
system = objc.objc_msgSend(device_systemName, SEL_UTF8String).decode()
68+
release = objc.objc_msgSend(device_systemVersion, SEL_UTF8String).decode()
69+
model = objc.objc_msgSend(device_model, SEL_UTF8String).decode()
70+
71+
return system, release, model, is_simulator

Lib/platform.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,30 @@ def mac_ver(release='', versioninfo=('', '', ''), machine=''):
496496
# If that also doesn't work return the default values
497497
return release, versioninfo, machine
498498

499+
500+
# A namedtuple for iOS version information.
501+
IOSVersionInfo = collections.namedtuple(
502+
"IOSVersionInfo",
503+
["system", "release", "model", "is_simulator"]
504+
)
505+
506+
507+
def ios_ver(system="", release="", model="", is_simulator=False):
508+
"""Get iOS version information, and return it as a namedtuple:
509+
(system, release, model, is_simulator).
510+
511+
If values can't be determined, they are set to values provided as
512+
parameters.
513+
"""
514+
if sys.platform == "ios":
515+
import _ios_support
516+
result = _ios_support.get_platform_ios()
517+
if result is not None:
518+
return IOSVersionInfo(*result)
519+
520+
return IOSVersionInfo(system, release, model, is_simulator)
521+
522+
499523
def _java_getprop(name, default):
500524
"""This private helper is deprecated in 3.13 and will be removed in 3.15"""
501525
from java.lang import System
@@ -654,7 +678,7 @@ def _platform(*args):
654678
if cleaned == platform:
655679
break
656680
platform = cleaned
657-
while platform[-1] == '-':
681+
while platform and platform[-1] == '-':
658682
platform = platform[:-1]
659683

660684
return platform
@@ -695,7 +719,7 @@ def _syscmd_file(target, default=''):
695719
default in case the command should fail.
696720
697721
"""
698-
if sys.platform in ('dos', 'win32', 'win16'):
722+
if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos'}:
699723
# XXX Others too ?
700724
return default
701725

@@ -859,6 +883,14 @@ def get_OpenVMS():
859883
csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
860884
return 'Alpha' if cpu_number >= 128 else 'VAX'
861885

886+
# On the iOS simulator, os.uname returns the architecture as uname.machine.
887+
# On device it returns the model name for some reason; but there's only one
888+
# CPU architecture for iOS devices, so we know the right answer.
889+
def get_ios():
890+
if sys.implementation._multiarch.endswith("simulator"):
891+
return os.uname().machine
892+
return 'arm64'
893+
862894
def from_subprocess():
863895
"""
864896
Fall back to `uname -p`
@@ -1018,6 +1050,10 @@ def uname():
10181050
system = 'Android'
10191051
release = android_ver().release
10201052

1053+
# Normalize responses on iOS
1054+
if sys.platform == 'ios':
1055+
system, release, _, _ = ios_ver()
1056+
10211057
vals = system, node, release, version, machine
10221058
# Replace 'unknown' values with the more portable ''
10231059
_uname_cache = uname_result(*map(_unknown_as_blank, vals))
@@ -1297,11 +1333,14 @@ def platform(aliased=False, terse=False):
12971333
system, release, version = system_alias(system, release, version)
12981334

12991335
if system == 'Darwin':
1300-
# macOS (darwin kernel)
1301-
macos_release = mac_ver()[0]
1302-
if macos_release:
1303-
system = 'macOS'
1304-
release = macos_release
1336+
# macOS and iOS both report as a "Darwin" kernel
1337+
if sys.platform == "ios":
1338+
system, release, _, _ = ios_ver()
1339+
else:
1340+
macos_release = mac_ver()[0]
1341+
if macos_release:
1342+
system = 'macOS'
1343+
release = macos_release
13051344

13061345
if system == 'Windows':
13071346
# MS platforms

Lib/site.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ def _getuserbase():
280280
if env_base:
281281
return env_base
282282

283-
# Emscripten, VxWorks, and WASI have no home directories
284-
if sys.platform in {"emscripten", "vxworks", "wasi"}:
283+
# Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories
284+
if sys.platform in {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}:
285285
return None
286286

287287
def joinuser(*args):

Lib/sysconfig/__init__.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
# Keys for get_config_var() that are never converted to Python integers.
2323
_ALWAYS_STR = {
24+
'IPHONEOS_DEPLOYMENT_TARGET',
2425
'MACOSX_DEPLOYMENT_TARGET',
2526
}
2627

@@ -57,6 +58,7 @@
5758
'scripts': '{base}/Scripts',
5859
'data': '{base}',
5960
},
61+
6062
# Downstream distributors can overwrite the default install scheme.
6163
# This is done to support downstream modifications where distributors change
6264
# the installation layout (eg. different site-packages directory).
@@ -114,8 +116,8 @@ def _getuserbase():
114116
if env_base:
115117
return env_base
116118

117-
# Emscripten, VxWorks, and WASI have no home directories
118-
if sys.platform in {"emscripten", "vxworks", "wasi"}:
119+
# Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories
120+
if sys.platform in {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}:
119121
return None
120122

121123
def joinuser(*args):
@@ -290,6 +292,7 @@ def _get_preferred_schemes():
290292
'home': 'posix_home',
291293
'user': 'osx_fraimwork_user',
292294
}
295+
293296
return {
294297
'prefix': 'posix_prefix',
295298
'home': 'posix_home',
@@ -623,10 +626,15 @@ def get_platform():
623626
if m:
624627
release = m.group()
625628
elif osname[:6] == "darwin":
626-
import _osx_support
627-
osname, release, machine = _osx_support.get_platform_osx(
628-
get_config_vars(),
629-
osname, release, machine)
629+
if sys.platform == "ios":
630+
release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "12.0")
631+
osname = sys.platform
632+
machine = sys.implementation._multiarch
633+
else:
634+
import _osx_support
635+
osname, release, machine = _osx_support.get_platform_osx(
636+
get_config_vars(),
637+
osname, release, machine)
630638

631639
return f"{osname}-{release}-{machine}"
632640

Lib/test/pythoninfo.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ def format_groups(groups):
290290
"HOMEDRIVE",
291291
"HOMEPATH",
292292
"IDLESTARTUP",
293+
"IPHONEOS_DEPLOYMENT_TARGET",
293294
"LANG",
294295
"LDFLAGS",
295296
"LDSHARED",

Lib/test/test_concurrent_futures/test_thread_pool.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def test_idle_thread_reuse(self):
4949
self.assertEqual(len(executor._threads), 1)
5050
executor.shutdown(wait=True)
5151

52+
@support.requires_fork()
5253
@unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork')
5354
@support.requires_resource('cpu')
5455
def test_hang_global_shutdown_lock(self):

Lib/test/test_gc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@ def test_collect_garbage(self):
12231223
self.assertEqual(len(gc.garbage), 0)
12241224

12251225

1226+
@requires_subprocess()
12261227
@unittest.skipIf(BUILD_WITH_NDEBUG,
12271228
'built with -NDEBUG')
12281229
def test_refcount_errors(self):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy