| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b448982 commit f006338
22 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -784,6 +784,11 @@ process and user. | |||
| 784 | 784 | :func:`socket.gethostname` or even | |
| 785 | 785 | ``socket.gethostbyaddr(socket.gethostname())``. | |
| 786 | 786 | ||
| 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 | + | ||
| 787 | 792 | .. availability:: Unix. | |
| 788 | 793 | ||
| 789 | 794 | .. versionchanged:: 3.3 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -148,6 +148,9 @@ Cross Platform | |||
| 148 | 148 | Returns the system/OS name, such as ``'Linux'``, ``'Darwin'``, ``'Java'``, | |
| 149 | 149 | ``'Windows'``. An empty string is returned if the value cannot be determined. | |
| 150 | 150 | ||
| 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()`. | ||
| 151 | 154 | ||
| 152 | 155 | .. function:: system_alias(system, release, version) | |
| 153 | 156 | ||
@@ -161,6 +164,8 @@ Cross Platform | |||
| 161 | 164 | Returns the system's release version, e.g. ``'#3 on degas'``. An empty string is | |
| 162 | 165 | returned if the value cannot be determined. | |
| 163 | 166 | ||
| 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()`. | ||
| 164 | 169 | ||
| 165 | 170 | .. function:: uname() | |
| 166 | 171 | ||
@@ -238,7 +243,6 @@ Windows Platform | |||
| 238 | 243 | macOS Platform | |
| 239 | 244 | -------------- | |
| 240 | 245 | ||
| 241 | - | ||
| 242 | 246 | .. function:: mac_ver(release='', versioninfo=('','',''), machine='') | |
| 243 | 247 | ||
| 244 | 248 | Get macOS version information and return it as tuple ``(release, versioninfo, | |
@@ -248,6 +252,24 @@ macOS Platform | |||
| 248 | 252 | Entries which cannot be determined are set to ``''``. All tuple entries are | |
| 249 | 253 | strings. | |
| 250 | 254 | ||
| 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 | + | ||
| 251 | 273 | ||
| 252 | 274 | Unix Platforms | |
| 253 | 275 | -------------- | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,6 +33,13 @@ allow the remote browser to maintain its own windows on the display. If remote | |||
| 33 | 33 | browsers are not available on Unix, the controlling process will launch a new | |
| 34 | 34 | browser and wait. | |
| 35 | 35 | ||
| 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 | + | ||
| 36 | 43 | The script :program:`webbrowser` can be used as a command-line interface for the | |
| 37 | 44 | module. It accepts a URL as the argument. It accepts the following optional | |
| 38 | 45 | 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. | |||
| 147 | 154 | +------------------------+-----------------------------------------+-------+ | |
| 148 | 155 | | ``'chromium-browser'`` | ``Chromium('chromium-browser')`` | | | |
| 149 | 156 | +------------------------+-----------------------------------------+-------+ | |
| 157 | + | ``'iosbrowser'`` | ``IOSBrowser`` | \(4) | | ||
| 158 | + +------------------------+-----------------------------------------+-------+ | ||
| 150 | 159 | ||
| 151 | 160 | Notes: | |
| 152 | 161 | ||
@@ -161,7 +170,10 @@ Notes: | |||
| 161 | 170 | Only on Windows platforms. | |
| 162 | 171 | ||
| 163 | 172 | (3) | |
| 164 | - Only on macOS platform. | ||
| 173 | + Only on macOS. | ||
| 174 | + | ||
| 175 | + (4) | ||
| 176 | + Only on iOS. | ||
| 165 | 177 | ||
| 166 | 178 | .. versionadded:: 3.2 | |
| 167 | 179 | A new :class:`!MacOSXOSAScript` class has been added | |
@@ -176,6 +188,9 @@ Notes: | |||
| 176 | 188 | Removed browsers include Grail, Mosaic, Netscape, Galeon, | |
| 177 | 189 | Skipstone, Iceape, and Firefox versions 35 and below. | |
| 178 | 190 | ||
| 191 | + .. versionchanged:: 3.13 | ||
| 192 | + Support for iOS has been added. | ||
| 193 | + | ||
| 179 | 194 | Here are some simple examples:: | |
| 180 | 195 | ||
| 181 | 196 | url = 'https://docs.python.org/' | |
| Original file line number | Diff line number | Diff 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 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -496,6 +496,30 @@ def mac_ver(release='', versioninfo=('', '', ''), machine=''): | |||
| 496 | 496 | # If that also doesn't work return the default values | |
| 497 | 497 | return release, versioninfo, machine | |
| 498 | 498 | ||
| 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 | + | ||
| 499 | 523 | def _java_getprop(name, default): | |
| 500 | 524 | """This private helper is deprecated in 3.13 and will be removed in 3.15""" | |
| 501 | 525 | from java.lang import System | |
@@ -654,7 +678,7 @@ def _platform(*args): | |||
| 654 | 678 | if cleaned == platform: | |
| 655 | 679 | break | |
| 656 | 680 | platform = cleaned | |
| 657 | - while platform[-1] == '-': | ||
| 681 | + while platform and platform[-1] == '-': | ||
| 658 | 682 | platform = platform[:-1] | |
| 659 | 683 | ||
| 660 | 684 | return platform | |
@@ -695,7 +719,7 @@ def _syscmd_file(target, default=''): | |||
| 695 | 719 | default in case the command should fail. | |
| 696 | 720 | ||
| 697 | 721 | """ | |
| 698 | - if sys.platform in ('dos', 'win32', 'win16'): | ||
| 722 | + if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos'}: | ||
| 699 | 723 | # XXX Others too ? | |
| 700 | 724 | return default | |
| 701 | 725 | ||
@@ -859,6 +883,14 @@ def get_OpenVMS(): | |||
| 859 | 883 | csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0) | |
| 860 | 884 | return 'Alpha' if cpu_number >= 128 else 'VAX' | |
| 861 | 885 | ||
| 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 | + | ||
| 862 | 894 | def from_subprocess(): | |
| 863 | 895 | """ | |
| 864 | 896 | Fall back to `uname -p` | |
@@ -1018,6 +1050,10 @@ def uname(): | |||
| 1018 | 1050 | system = 'Android' | |
| 1019 | 1051 | release = android_ver().release | |
| 1020 | 1052 | ||
| 1053 | + # Normalize responses on iOS | ||
| 1054 | + if sys.platform == 'ios': | ||
| 1055 | + system, release, _, _ = ios_ver() | ||
| 1056 | + | ||
| 1021 | 1057 | vals = system, node, release, version, machine | |
| 1022 | 1058 | # Replace 'unknown' values with the more portable '' | |
| 1023 | 1059 | _uname_cache = uname_result(*map(_unknown_as_blank, vals)) | |
@@ -1297,11 +1333,14 @@ def platform(aliased=False, terse=False): | |||
| 1297 | 1333 | system, release, version = system_alias(system, release, version) | |
| 1298 | 1334 | ||
| 1299 | 1335 | 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 | ||
| 1305 | 1344 | ||
| 1306 | 1345 | if system == 'Windows': | |
| 1307 | 1346 | # MS platforms | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -280,8 +280,8 @@ def _getuserbase(): | |||
| 280 | 280 | if env_base: | |
| 281 | 281 | return env_base | |
| 282 | 282 | ||
| 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"}: | ||
| 285 | 285 | return None | |
| 286 | 286 | ||
| 287 | 287 | def joinuser(*args): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | 22 | # Keys for get_config_var() that are never converted to Python integers. | |
| 23 | 23 | _ALWAYS_STR = { | |
| 24 | + 'IPHONEOS_DEPLOYMENT_TARGET', | ||
| 24 | 25 | 'MACOSX_DEPLOYMENT_TARGET', | |
| 25 | 26 | } | |
| 26 | 27 | ||
@@ -57,6 +58,7 @@ | |||
| 57 | 58 | 'scripts': '{base}/Scripts', | |
| 58 | 59 | 'data': '{base}', | |
| 59 | 60 | }, | |
| 61 | + | ||
| 60 | 62 | # Downstream distributors can overwrite the default install scheme. | |
| 61 | 63 | # This is done to support downstream modifications where distributors change | |
| 62 | 64 | # the installation layout (eg. different site-packages directory). | |
@@ -114,8 +116,8 @@ def _getuserbase(): | |||
| 114 | 116 | if env_base: | |
| 115 | 117 | return env_base | |
| 116 | 118 | ||
| 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"}: | ||
| 119 | 121 | return None | |
| 120 | 122 | ||
| 121 | 123 | def joinuser(*args): | |
@@ -290,6 +292,7 @@ def _get_preferred_schemes(): | |||
| 290 | 292 | 'home': 'posix_home', | |
| 291 | 293 | 'user': 'osx_framework_user', | |
| 292 | 294 | } | |
| 295 | + | ||
| 293 | 296 | return { | |
| 294 | 297 | 'prefix': 'posix_prefix', | |
| 295 | 298 | 'home': 'posix_home', | |
@@ -623,10 +626,15 @@ def get_platform(): | |||
| 623 | 626 | if m: | |
| 624 | 627 | release = m.group() | |
| 625 | 628 | 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) | ||
| 630 | 638 | ||
| 631 | 639 | return f"{osname}-{release}-{machine}" | |
| 632 | 640 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -290,6 +290,7 @@ def format_groups(groups): | |||
| 290 | 290 | "HOMEDRIVE", | |
| 291 | 291 | "HOMEPATH", | |
| 292 | 292 | "IDLESTARTUP", | |
| 293 | + "IPHONEOS_DEPLOYMENT_TARGET", | ||
| 293 | 294 | "LANG", | |
| 294 | 295 | "LDFLAGS", | |
| 295 | 296 | "LDSHARED", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,6 +49,7 @@ def test_idle_thread_reuse(self): | |||
| 49 | 49 | self.assertEqual(len(executor._threads), 1) | |
| 50 | 50 | executor.shutdown(wait=True) | |
| 51 | 51 | ||
| 52 | + @support.requires_fork() | ||
| 52 | 53 | @unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork') | |
| 53 | 54 | @support.requires_resource('cpu') | |
| 54 | 55 | def test_hang_global_shutdown_lock(self): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1223,6 +1223,7 @@ def test_collect_garbage(self): | |||
| 1223 | 1223 | self.assertEqual(len(gc.garbage), 0) | |
| 1224 | 1224 | ||
| 1225 | 1225 | ||
| 1226 | + @requires_subprocess() | ||
| 1226 | 1227 | @unittest.skipIf(BUILD_WITH_NDEBUG, | |
| 1227 | 1228 | 'built with -NDEBUG') | |
| 1228 | 1229 | def test_refcount_errors(self): | |
| Back | FazBrowse Home | New Git URL |
0 commit comments