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-71042: Add platform.android_ver#116674
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
Changes from all commits
ead6dcb8934a4e4dca7c44108dfc646441b4f65e8e9fd7f44b64f1f553e6511File 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 |
|---|---|---|
| @@ -542,6 +542,47 @@ def java_ver(release='', vendor='', vminfo=('', '', ''), osinfo=('', '', '')): | ||
| return release, vendor, vminfo, osinfo | ||
| AndroidVer = collections.namedtuple( | ||
| "AndroidVer", "release api_level manufacturer model device is_emulator") | ||
| def android_ver(release="", api_level=0, manufacturer="", model="", device="", | ||
| is_emulator=False): | ||
| if sys.platform == "android": | ||
| try: | ||
| from ctypes import CDLL, c_char_p, create_string_buffer | ||
| except ImportError: | ||
| pass | ||
| else: | ||
| # An NDK developer confirmed that this is an officially-supported | ||
| # API (https://stackoverflow.com/a/28416743). Use `getattr` to avoid | ||
| # private name mangling. | ||
| system_property_get = getattr(CDLL("libc.so"), "__system_property_get") | ||
| system_property_get.argtypes = (c_char_p, c_char_p) | ||
| def getprop(name, default): | ||
| # https://android.googlesource.com/platform/bionic/+/refs/tags/android-5.0.0_r1/libc/include/sys/system_properties.h#39 | ||
| PROP_VALUE_MAX = 92 | ||
| buffer = create_string_buffer(PROP_VALUE_MAX) | ||
| length = system_property_get(name.encode("UTF-8"), buffer) | ||
| if length == 0: | ||
| # This API doesn’t distinguish between an empty property and | ||
| # a missing one. | ||
| return default | ||
| else: | ||
| return buffer.value.decode("UTF-8", "backslashreplace") | ||
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. Did you consider MemberAuthor
| ||
| release = getprop("ro.build.version.release", release) | ||
| api_level = int(getprop("ro.build.version.sdk", api_level)) | ||
| manufacturer = getprop("ro.product.manufacturer", manufacturer) | ||
| model = getprop("ro.product.model", model) | ||
| device = getprop("ro.product.device", device) | ||
| is_emulator = getprop("ro.kernel.qemu", "0") == "1" | ||
| return AndroidVer( | ||
| release, api_level, manufacturer, model, device, is_emulator) | ||
| ### System name aliasing | ||
| def system_alias(system, release, version): | ||
| @@ -972,6 +1013,11 @@ def uname(): | ||
| system = 'Windows' | ||
| release = 'Vista' | ||
| # On Android, return the name and version of the OS rather than the kernel. | ||
| if sys.platform == 'android': | ||
| system = 'Android' | ||
| release = android_ver().release | ||
| vals = system, node, release, version, machine | ||
| # Replace 'unknown' values with the more portable '' | ||
| _uname_cache = uname_result(*map(_unknown_as_blank, vals)) | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -179,6 +179,9 @@ def collect_platform(info_add): | ||||||||
| info_add(f'platform.freedesktop_os_release[{key}]', | ||||||||
| os_release[key]) | ||||||||
| if sys.platform == 'android': | ||||||||
| call_func(info_add, 'platform.android_ver', platform, 'android_ver') | ||||||||
Comment on lines +182 to +183 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. FYI you can just call: Suggested change
It does nothing if the function doesn't exist. MemberAuthor 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. Like the other | ||||||||
| def collect_locale(info_add): | ||||||||
| import locale | ||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -219,6 +219,19 @@ def test_uname(self): | ||
| self.assertEqual(res[-1], res.processor) | ||
| self.assertEqual(len(res), 6) | ||
| if os.name == "posix": | ||
| uname = os.uname() | ||
| self.assertEqual(res.node, uname.nodename) | ||
| self.assertEqual(res.version, uname.version) | ||
| self.assertEqual(res.machine, uname.machine) | ||
mhsmith marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| if sys.platform == "android": | ||
| self.assertEqual(res.system, "Android") | ||
| self.assertEqual(res.release, platform.android_ver().release) | ||
| else: | ||
| self.assertEqual(res.system, uname.sysname) | ||
| self.assertEqual(res.release, uname.release) | ||
| @unittest.skipUnless(sys.platform.startswith('win'), "windows only test") | ||
| def test_uname_win32_without_wmi(self): | ||
| def raises_oserror(*a): | ||
| @@ -430,6 +443,43 @@ def test_libc_ver(self): | ||
| self.assertEqual(platform.libc_ver(filename, chunksize=chunksize), | ||
| ('glibc', '1.23.4')) | ||
| def test_android_ver(self): | ||
| res = platform.android_ver() | ||
| self.assertIsInstance(res, tuple) | ||
| self.assertEqual(res, (res.release, res.api_level, res.manufacturer, | ||
| res.model, res.device, res.is_emulator)) | ||
| if sys.platform == "android": | ||
| for name in ["release", "manufacturer", "model", "device"]: | ||
| with self.subTest(name): | ||
| value = getattr(res, name) | ||
| self.assertIsInstance(value, str) | ||
| self.assertNotEqual(value, "") | ||
| self.assertIsInstance(res.api_level, int) | ||
| self.assertGreaterEqual(res.api_level, sys.getandroidapilevel()) | ||
| self.assertIsInstance(res.is_emulator, bool) | ||
| # When not running on Android, it should return the default values. | ||
| else: | ||
| self.assertEqual(res.release, "") | ||
| self.assertEqual(res.api_level, 0) | ||
| self.assertEqual(res.manufacturer, "") | ||
| self.assertEqual(res.model, "") | ||
| self.assertEqual(res.device, "") | ||
| self.assertEqual(res.is_emulator, False) | ||
| # Default values may also be overridden using parameters. | ||
| res = platform.android_ver( | ||
| "alpha", 1, "bravo", "charlie", "delta", True) | ||
| self.assertEqual(res.release, "alpha") | ||
| self.assertEqual(res.api_level, 1) | ||
| self.assertEqual(res.manufacturer, "bravo") | ||
| self.assertEqual(res.model, "charlie") | ||
| self.assertEqual(res.device, "delta") | ||
| self.assertEqual(res.is_emulator, True) | ||
| @support.cpython_only | ||
| def test__comparable_version(self): | ||
| from platform import _comparable_version as V | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Add :func:`platform.android_ver`, which provides device and OS information | ||
| on Android. |
Uh oh!
There was an error while loading. Please reload this page.