Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
gh-114099: Additions to standard library to support iOS#117052
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
760751bb41f9a40f3e9bc1a9d965c7fe185732c4da97a081d95c367d3d6d875d12cfa095d11fb48f4c1af584d299515f75cf0b5ff96aa04224b3662a4e09c941a3c1a84ba76041948499a91933e6550b786543767a4dcaf44513264386a7ac1a1f0b61559acabc2034096078a44bbf797419002c121d5f1ac4b26857a0c3aa65dc261e51ff2ee4abaFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| importsys | ||
| try: | ||
| fromctypesimportcdll, c_void_p, c_char_p, util | ||
| exceptImportError: | ||
| # ctypes is an optional module. If it's not present, we're limited in what | ||
| # we can tell about the system, but we don't want to prevent the module | ||
| # from working. | ||
| print("ctypes isn't available; iOS system calls will not be available") | ||
| objc=None | ||
| else: | ||
| # ctypes is available. Load the ObjC library, and wrap the objc_getClass, | ||
| # sel_registerName methods | ||
| lib=util.find_library("objc") | ||
| iflibisNone: | ||
| # Failed to load the objc library | ||
| raiseRuntimeError("ObjC runtime library couldn't be loaded") | ||
| objc=cdll.LoadLibrary(lib) | ||
| objc.objc_getClass.restype=c_void_p | ||
| objc.objc_getClass.argtypes= [c_char_p] | ||
| objc.sel_registerName.restype=c_void_p | ||
| objc.sel_registerName.argtypes= [c_char_p] | ||
| defget_platform_ios(): | ||
| # Determine if this is a simulator using the multiarch value | ||
| is_simulator=sys.implementation._multiarch.endswith("simulator") | ||
| # We can't use ctypes; abort | ||
| ifnotobjc: | ||
| returnNone | ||
| # Most of the methods return ObjC objects | ||
| objc.objc_msgSend.restype=c_void_p | ||
| # All the methods used have no arguments. | ||
| objc.objc_msgSend.argtypes= [c_void_p, c_void_p] | ||
| # Equivalent of: | ||
| # device = [UIDevice currentDevice] | ||
| UIDevice=objc.objc_getClass(b"UIDevice") | ||
| SEL_currentDevice=objc.sel_registerName(b"currentDevice") | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
https://peps.python.org/pep-0008/#function-and-variable-names ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes - the intention was to mirror the objc naming, so that it's a little easier to see that the name comes from an "alien space", and might have some additional considerations - a sort of very weak Hungarian notation. In terms of pure functionality, it doesn't have any impact on the operation of the code. Any variable name will do; this naming convention is entirely as an affordance to future readers. For my money, the "hey, that's weird - they're not camel case" reaction is mildly desirable in this case. | ||
| device=objc.objc_msgSend(UIDevice, SEL_currentDevice) | ||
| # Equivalent of: | ||
| # device_systemVersion = [device systemVersion] | ||
| SEL_systemVersion=objc.sel_registerName(b"systemVersion") | ||
| device_systemVersion=objc.objc_msgSend(device, SEL_systemVersion) | ||
| # Equivalent of: | ||
| # device_systemName = [device systemName] | ||
| SEL_systemName=objc.sel_registerName(b"systemName") | ||
| device_systemName=objc.objc_msgSend(device, SEL_systemName) | ||
| # Equivalent of: | ||
| # device_model = [device model] | ||
| SEL_model=objc.sel_registerName(b"model") | ||
| device_model=objc.objc_msgSend(device, SEL_model) | ||
| # UTF8String returns a const char*; | ||
| SEL_UTF8String=objc.sel_registerName(b"UTF8String") | ||
| objc.objc_msgSend.restype=c_char_p | ||
| # Equivalent of: | ||
| # system = [device_systemName UTF8String] | ||
| # release = [device_systemVersion UTF8String] | ||
| # model = [device_model UTF8String] | ||
| system=objc.objc_msgSend(device_systemName, SEL_UTF8String).decode() | ||
| release=objc.objc_msgSend(device_systemVersion, SEL_UTF8String).decode() | ||
| model=objc.objc_msgSend(device_model, SEL_UTF8String).decode() | ||
| returnsystem, release, model, is_simulator | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -496,6 +496,30 @@ def mac_ver(release='', versioninfo=('', '', ''), machine=''): | ||||||||||||||
| # If that also doesn't work return the default values | ||||||||||||||
| return release, versioninfo, machine | ||||||||||||||
| # A namedtuple for iOS version information. | ||||||||||||||
| IOSVersionInfo = collections.namedtuple( | ||||||||||||||
| "IOSVersionInfo", | ||||||||||||||
| ["system", "release", "model", "is_simulator"] | ||||||||||||||
| ) | ||||||||||||||
| def ios_ver(system="", release="", model="", is_simulator=False): | ||||||||||||||
| """Get iOS version information, and return it as a namedtuple: | ||||||||||||||
| (system, release, model, is_simulator). | ||||||||||||||
| If values can't be determined, they are set to values provided as | ||||||||||||||
| parameters. | ||||||||||||||
| """ | ||||||||||||||
| if sys.platform == "ios": | ||||||||||||||
| import _ios_support | ||||||||||||||
| result = _ios_support.get_platform_ios() | ||||||||||||||
| if result is not None: | ||||||||||||||
| return IOSVersionInfo(*result) | ||||||||||||||
| return IOSVersionInfo(system, release, model, is_simulator) | ||||||||||||||
| def _java_getprop(name, default): | ||||||||||||||
| """This private helper is deprecated in 3.13 and will be removed in 3.15""" | ||||||||||||||
| from java.lang import System | ||||||||||||||
| @@ -654,7 +678,7 @@ def _platform(*args): | ||||||||||||||
| if cleaned == platform: | ||||||||||||||
| break | ||||||||||||||
| platform = cleaned | ||||||||||||||
| while platform[-1] == '-': | ||||||||||||||
| while platform and platform[-1] == '-': | ||||||||||||||
| platform = platform[:-1] | ||||||||||||||
| return platform | ||||||||||||||
| @@ -695,7 +719,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 | ||||||||||||||
| @@ -859,6 +883,14 @@ def get_OpenVMS(): | ||||||||||||||
| csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0) | ||||||||||||||
| return 'Alpha' if cpu_number >= 128 else 'VAX' | ||||||||||||||
| # On the iOS simulator, os.uname returns the architecture as uname.machine. | ||||||||||||||
| # On device it returns the model name for some reason; but there's only one | ||||||||||||||
| # CPU architecture for iOS devices, so we know the right answer. | ||||||||||||||
| def get_ios(): | ||||||||||||||
| if sys.implementation._multiarch.endswith("simulator"): | ||||||||||||||
| return os.uname().machine | ||||||||||||||
| return 'arm64' | ||||||||||||||
Comment on lines +890 to +892 Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggested change
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of the way the build works for iOS, I think we can assume that _multiarch is always present. ContributorAuthor
| ||||||||||||||
| def from_subprocess(): | ||||||||||||||
| """ | ||||||||||||||
| Fall back to `uname -p` | ||||||||||||||
| @@ -1018,6 +1050,10 @@ def uname(): | ||||||||||||||
| system = 'Android' | ||||||||||||||
| release = android_ver().release | ||||||||||||||
| # Normalize responses on iOS | ||||||||||||||
| if sys.platform == 'ios': | ||||||||||||||
| system, release, _, _ = ios_ver() | ||||||||||||||
| vals = system, node, release, version, machine | ||||||||||||||
| # Replace 'unknown' values with the more portable '' | ||||||||||||||
| _uname_cache = uname_result(*map(_unknown_as_blank, vals)) | ||||||||||||||
| @@ -1297,11 +1333,14 @@ 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 | ||||||||||||||
| # macOS and iOS both report as a "Darwin" kernel | ||||||||||||||
| if sys.platform == "ios": | ||||||||||||||
| system, release, _, _ = ios_ver() | ||||||||||||||
| else: | ||||||||||||||
| macos_release = mac_ver()[0] | ||||||||||||||
| if macos_release: | ||||||||||||||
| system = 'macOS' | ||||||||||||||
| release = macos_release | ||||||||||||||
| if system == 'Windows': | ||||||||||||||
| # MS platforms | ||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -21,6 +21,7 @@ | ||||||
| # Keys for get_config_var() that are never converted to Python integers. | ||||||
| _ALWAYS_STR ={ | ||||||
| 'IPHONEOS_DEPLOYMENT_TARGET', | ||||||
| 'MACOSX_DEPLOYMENT_TARGET', | ||||||
| } | ||||||
| @@ -57,6 +58,7 @@ | ||||||
| 'scripts': '{base}/Scripts', | ||||||
| 'data': '{base}', | ||||||
| }, | ||||||
| # Downstream distributors can overwrite the default install scheme. | ||||||
| # This is done to support downstream modifications where distributors change | ||||||
| # the installation layout (eg. different site-packages directory). | ||||||
| @@ -114,8 +116,8 @@ def _getuserbase(): | ||||||
| if env_base: | ||||||
| return env_base | ||||||
| # Emscripten, VxWorks, and WASI have no home directories | ||||||
| if sys.platform in{"emscripten", "vxworks", "wasi"}: | ||||||
| # Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories | ||||||
| if sys.platform in{"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}: | ||||||
| return None | ||||||
| def joinuser(*args): | ||||||
| @@ -290,6 +292,7 @@ def _get_preferred_schemes(): | ||||||
| 'home': 'posix_home', | ||||||
| 'user': 'osx_framework_user', | ||||||
| } | ||||||
| return{ | ||||||
| 'prefix': 'posix_prefix', | ||||||
| 'home': 'posix_home', | ||||||
| @@ -623,10 +626,15 @@ def get_platform(): | ||||||
| if m: | ||||||
| release = m.group() | ||||||
| elif osname[:6] == "darwin": | ||||||
| import _osx_support | ||||||
| osname, release, machine = _osx_support.get_platform_osx( | ||||||
| get_config_vars(), | ||||||
| osname, release, machine) | ||||||
| if sys.platform == "ios": | ||||||
| release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "12.0") | ||||||
| osname = sys.platform | ||||||
| machine = sys.implementation._multiarch | ||||||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggested change
ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again; this is iOS specific code. | ||||||
| else: | ||||||
| import _osx_support | ||||||
| osname, release, machine = _osx_support.get_platform_osx( | ||||||
| get_config_vars(), | ||||||
| osname, release, machine) | ||||||
| return f"{osname}-{release}-{machine}" | ||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above: iOS always has
_multiarch, andget_platform_ios()is only invoked byplatform.ios_ver(), after being gated to be iOS-specific.