mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 85c20374c0
			
		
	
	
		85c20374c0
		
			
		
	
	
	
	
		
			
			(cherry picked from commit 3185e3115c)
---------
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
		
	
			
		
			
				
	
	
		
			694 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			694 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import os
 | |
| import copy
 | |
| import pickle
 | |
| import platform
 | |
| import subprocess
 | |
| import sys
 | |
| import unittest
 | |
| from unittest import mock
 | |
| 
 | |
| from test import support
 | |
| from test.support import os_helper
 | |
| 
 | |
| try:
 | |
|     # Some of the iOS tests need ctypes to operate.
 | |
|     # Confirm that the ctypes module is available
 | |
|     # is available.
 | |
|     import _ctypes
 | |
| except ImportError:
 | |
|     _ctypes = None
 | |
| 
 | |
| FEDORA_OS_RELEASE = """\
 | |
| NAME=Fedora
 | |
| VERSION="32 (Thirty Two)"
 | |
| ID=fedora
 | |
| VERSION_ID=32
 | |
| VERSION_CODENAME=""
 | |
| PLATFORM_ID="platform:f32"
 | |
| PRETTY_NAME="Fedora 32 (Thirty Two)"
 | |
| ANSI_COLOR="0;34"
 | |
| LOGO=fedora-logo-icon
 | |
| CPE_NAME="cpe:/o:fedoraproject:fedora:32"
 | |
| HOME_URL="https://fedoraproject.org/"
 | |
| DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f32/system-administrators-guide/"
 | |
| SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
 | |
| BUG_REPORT_URL="https://bugzilla.redhat.com/"
 | |
| REDHAT_BUGZILLA_PRODUCT="Fedora"
 | |
| REDHAT_BUGZILLA_PRODUCT_VERSION=32
 | |
| REDHAT_SUPPORT_PRODUCT="Fedora"
 | |
| REDHAT_SUPPORT_PRODUCT_VERSION=32
 | |
| PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
 | |
| """
 | |
| 
 | |
| UBUNTU_OS_RELEASE = """\
 | |
| NAME="Ubuntu"
 | |
| VERSION="20.04.1 LTS (Focal Fossa)"
 | |
| ID=ubuntu
 | |
| ID_LIKE=debian
 | |
| PRETTY_NAME="Ubuntu 20.04.1 LTS"
 | |
| VERSION_ID="20.04"
 | |
| HOME_URL="https://www.ubuntu.com/"
 | |
| SUPPORT_URL="https://help.ubuntu.com/"
 | |
| BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
 | |
| PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
 | |
| VERSION_CODENAME=focal
 | |
| UBUNTU_CODENAME=focal
 | |
| """
 | |
| 
 | |
| TEST_OS_RELEASE = r"""
 | |
| # test data
 | |
| ID_LIKE="egg spam viking"
 | |
| EMPTY=
 | |
| # comments and empty lines are ignored
 | |
| 
 | |
| SINGLE_QUOTE='single'
 | |
| EMPTY_SINGLE=''
 | |
| DOUBLE_QUOTE="double"
 | |
| EMPTY_DOUBLE=""
 | |
| QUOTES="double\'s"
 | |
| SPECIALS="\$\`\\\'\""
 | |
| # invalid lines
 | |
| =invalid
 | |
| =
 | |
| INVALID
 | |
| IN-VALID=value
 | |
| IN VALID=value
 | |
| """
 | |
| 
 | |
| 
 | |
| class PlatformTest(unittest.TestCase):
 | |
|     def clear_caches(self):
 | |
|         platform._platform_cache.clear()
 | |
|         platform._sys_version_cache.clear()
 | |
|         platform._uname_cache = None
 | |
|         platform._os_release_cache = None
 | |
| 
 | |
|     def test_architecture(self):
 | |
|         res = platform.architecture()
 | |
| 
 | |
|     @os_helper.skip_unless_symlink
 | |
|     @support.requires_subprocess()
 | |
|     def test_architecture_via_symlink(self): # issue3762
 | |
|         with support.PythonSymlink() as py:
 | |
|             cmd = "-c", "import platform; print(platform.architecture())"
 | |
|             self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
 | |
| 
 | |
|     def test_platform(self):
 | |
|         for aliased in (False, True):
 | |
|             for terse in (False, True):
 | |
|                 res = platform.platform(aliased, terse)
 | |
| 
 | |
|     def test_system(self):
 | |
|         res = platform.system()
 | |
| 
 | |
|     def test_node(self):
 | |
|         res = platform.node()
 | |
| 
 | |
|     def test_release(self):
 | |
|         res = platform.release()
 | |
| 
 | |
|     def test_version(self):
 | |
|         res = platform.version()
 | |
| 
 | |
|     def test_machine(self):
 | |
|         res = platform.machine()
 | |
| 
 | |
|     def test_processor(self):
 | |
|         res = platform.processor()
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.save_version = sys.version
 | |
|         self.save_git = sys._git
 | |
|         self.save_platform = sys.platform
 | |
| 
 | |
|     def tearDown(self):
 | |
|         sys.version = self.save_version
 | |
|         sys._git = self.save_git
 | |
|         sys.platform = self.save_platform
 | |
| 
 | |
|     def test_sys_version(self):
 | |
|         # Old test.
 | |
|         for input, output in (
 | |
|             ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]',
 | |
|              ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')),
 | |
|             ('2.4.3 (truncation, date, t) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', 'date t', 'GCC')),
 | |
|             ('2.4.3 (truncation, date, ) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
 | |
|             ('2.4.3 (truncation, date,) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
 | |
|             ('2.4.3 (truncation, date) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
 | |
|             ('2.4.3 (truncation, d) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', 'd', 'GCC')),
 | |
|             ('2.4.3 (truncation, ) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
 | |
|             ('2.4.3 (truncation,) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
 | |
|             ('2.4.3 (truncation) \n[GCC]',
 | |
|              ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
 | |
|             ):
 | |
|             # branch and revision are not "parsed", but fetched
 | |
|             # from sys._git.  Ignore them
 | |
|             (name, version, branch, revision, buildno, builddate, compiler) \
 | |
|                    = platform._sys_version(input)
 | |
|             self.assertEqual(
 | |
|                 (name, version, '', '', buildno, builddate, compiler), output)
 | |
| 
 | |
|         # Tests for python_implementation(), python_version(), python_branch(),
 | |
|         # python_revision(), python_build(), and python_compiler().
 | |
|         sys_versions = {
 | |
|             ("2.6.1 (r261:67515, Dec  6 2008, 15:26:00) \n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]",
 | |
|              ('CPython', 'tags/r261', '67515'), self.save_platform)
 | |
|             :
 | |
|                 ("CPython", "2.6.1", "tags/r261", "67515",
 | |
|                  ('r261:67515', 'Dec  6 2008 15:26:00'),
 | |
|                  'GCC 4.0.1 (Apple Computer, Inc. build 5370)'),
 | |
| 
 | |
|             ("3.10.8 (tags/v3.10.8:aaaf517424, Feb 14 2023, 16:28:12) [GCC 9.4.0]",
 | |
|              None, "linux")
 | |
|             :
 | |
|                 ('CPython', '3.10.8', '', '',
 | |
|                 ('tags/v3.10.8:aaaf517424', 'Feb 14 2023 16:28:12'), 'GCC 9.4.0'),
 | |
| 
 | |
|             ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]",
 | |
|             ('Jython', 'trunk', '6107'), "java1.5.0_16")
 | |
|             :
 | |
|                 ("Jython", "2.5.0", "trunk", "6107",
 | |
|                  ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"),
 | |
| 
 | |
|             ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]",
 | |
|              ('PyPy', 'trunk', '63378'), self.save_platform)
 | |
|             :
 | |
|                 ("PyPy", "2.5.2", "trunk", "63378", ('63378', 'Mar 26 2009'),
 | |
|                  "")
 | |
|             }
 | |
|         for (version_tag, scm, sys_platform), info in \
 | |
|                 sys_versions.items():
 | |
|             sys.version = version_tag
 | |
|             if scm is None:
 | |
|                 if hasattr(sys, "_git"):
 | |
|                     del sys._git
 | |
|             else:
 | |
|                 sys._git = scm
 | |
|             if sys_platform is not None:
 | |
|                 sys.platform = sys_platform
 | |
|             self.assertEqual(platform.python_implementation(), info[0])
 | |
|             self.assertEqual(platform.python_version(), info[1])
 | |
|             self.assertEqual(platform.python_branch(), info[2])
 | |
|             self.assertEqual(platform.python_revision(), info[3])
 | |
|             self.assertEqual(platform.python_build(), info[4])
 | |
|             self.assertEqual(platform.python_compiler(), info[5])
 | |
| 
 | |
|         with self.assertRaises(ValueError):
 | |
|             platform._sys_version('2. 4.3 (truncation) \n[GCC]')
 | |
| 
 | |
|     def test_system_alias(self):
 | |
|         res = platform.system_alias(
 | |
|             platform.system(),
 | |
|             platform.release(),
 | |
|             platform.version(),
 | |
|         )
 | |
| 
 | |
|     def test_uname(self):
 | |
|         res = platform.uname()
 | |
|         self.assertTrue(any(res))
 | |
|         self.assertEqual(res[0], res.system)
 | |
|         self.assertEqual(res[-6], res.system)
 | |
|         self.assertEqual(res[1], res.node)
 | |
|         self.assertEqual(res[-5], res.node)
 | |
|         self.assertEqual(res[2], res.release)
 | |
|         self.assertEqual(res[-4], res.release)
 | |
|         self.assertEqual(res[3], res.version)
 | |
|         self.assertEqual(res[-3], res.version)
 | |
|         self.assertEqual(res[4], res.machine)
 | |
|         self.assertEqual(res[-2], res.machine)
 | |
|         self.assertEqual(res[5], res.processor)
 | |
|         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)
 | |
| 
 | |
|             if sys.platform == "android":
 | |
|                 self.assertEqual(res.system, "Android")
 | |
|                 self.assertEqual(res.release, platform.android_ver().release)
 | |
|             elif sys.platform == "ios":
 | |
|                 # Platform module needs ctypes for full operation. If ctypes
 | |
|                 # isn't available, there's no ObjC module, and dummy values are
 | |
|                 # returned.
 | |
|                 if _ctypes:
 | |
|                     self.assertIn(res.system, {"iOS", "iPadOS"})
 | |
|                     self.assertEqual(res.release, platform.ios_ver().release)
 | |
|                 else:
 | |
|                     self.assertEqual(res.system, "")
 | |
|                     self.assertEqual(res.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):
 | |
|             raise OSError()
 | |
| 
 | |
|         with support.swap_attr(platform, '_wmi_query', raises_oserror):
 | |
|             self.test_uname()
 | |
| 
 | |
|     def test_uname_cast_to_tuple(self):
 | |
|         res = platform.uname()
 | |
|         expected = (
 | |
|             res.system, res.node, res.release, res.version, res.machine,
 | |
|             res.processor,
 | |
|         )
 | |
|         self.assertEqual(tuple(res), expected)
 | |
| 
 | |
|     def test_uname_replace(self):
 | |
|         res = platform.uname()
 | |
|         new = res._replace(
 | |
|             system='system', node='node', release='release',
 | |
|             version='version', machine='machine')
 | |
|         self.assertEqual(new.system, 'system')
 | |
|         self.assertEqual(new.node, 'node')
 | |
|         self.assertEqual(new.release, 'release')
 | |
|         self.assertEqual(new.version, 'version')
 | |
|         self.assertEqual(new.machine, 'machine')
 | |
|         # processor cannot be replaced
 | |
|         self.assertEqual(new.processor, res.processor)
 | |
| 
 | |
|     def test_uname_copy(self):
 | |
|         uname = platform.uname()
 | |
|         self.assertEqual(copy.copy(uname), uname)
 | |
|         self.assertEqual(copy.deepcopy(uname), uname)
 | |
| 
 | |
|     def test_uname_pickle(self):
 | |
|         orig = platform.uname()
 | |
|         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
 | |
|             with self.subTest(protocol=proto):
 | |
|                 pickled = pickle.dumps(orig, proto)
 | |
|                 restored = pickle.loads(pickled)
 | |
|                 self.assertEqual(restored, orig)
 | |
| 
 | |
|     def test_uname_slices(self):
 | |
|         res = platform.uname()
 | |
|         expected = tuple(res)
 | |
|         self.assertEqual(res[:], expected)
 | |
|         self.assertEqual(res[:5], expected[:5])
 | |
| 
 | |
|     def test_uname_fields(self):
 | |
|         self.assertIn('processor', platform.uname()._fields)
 | |
| 
 | |
|     def test_uname_asdict(self):
 | |
|         res = platform.uname()._asdict()
 | |
|         self.assertEqual(len(res), 6)
 | |
|         self.assertIn('processor', res)
 | |
| 
 | |
|     @unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used")
 | |
|     @support.requires_subprocess()
 | |
|     def test_uname_processor(self):
 | |
|         """
 | |
|         On some systems, the processor must match the output
 | |
|         of 'uname -p'. See Issue 35967 for rationale.
 | |
|         """
 | |
|         try:
 | |
|             proc_res = subprocess.check_output(['uname', '-p'], text=True).strip()
 | |
|             expect = platform._unknown_as_blank(proc_res)
 | |
|         except (OSError, subprocess.CalledProcessError):
 | |
|             expect = ''
 | |
|         self.assertEqual(platform.uname().processor, expect)
 | |
| 
 | |
|     @unittest.skipUnless(sys.platform.startswith('win'), "windows only test")
 | |
|     def test_uname_win32_ARCHITEW6432(self):
 | |
|         # Issue 7860: make sure we get architecture from the correct variable
 | |
|         # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be
 | |
|         # using it, per
 | |
|         # http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx
 | |
| 
 | |
|         # We also need to suppress WMI checks, as those are reliable and
 | |
|         # overrule the environment variables
 | |
|         def raises_oserror(*a):
 | |
|             raise OSError()
 | |
| 
 | |
|         with support.swap_attr(platform, '_wmi_query', raises_oserror):
 | |
|             with os_helper.EnvironmentVarGuard() as environ:
 | |
|                 try:
 | |
|                     del environ['PROCESSOR_ARCHITEW6432']
 | |
|                     environ['PROCESSOR_ARCHITECTURE'] = 'foo'
 | |
|                     platform._uname_cache = None
 | |
|                     system, node, release, version, machine, processor = platform.uname()
 | |
|                     self.assertEqual(machine, 'foo')
 | |
|                     environ['PROCESSOR_ARCHITEW6432'] = 'bar'
 | |
|                     platform._uname_cache = None
 | |
|                     system, node, release, version, machine, processor = platform.uname()
 | |
|                     self.assertEqual(machine, 'bar')
 | |
|                 finally:
 | |
|                     platform._uname_cache = None
 | |
| 
 | |
|     def test_java_ver(self):
 | |
|         import re
 | |
|         msg = re.escape(
 | |
|             "'java_ver' is deprecated and slated for removal in Python 3.15"
 | |
|         )
 | |
|         with self.assertWarnsRegex(DeprecationWarning, msg):
 | |
|             res = platform.java_ver()
 | |
|         self.assertEqual(len(res), 4)
 | |
| 
 | |
|     @unittest.skipUnless(support.MS_WINDOWS, 'This test only makes sense on Windows')
 | |
|     def test_win32_ver(self):
 | |
|         release1, version1, csd1, ptype1 = 'a', 'b', 'c', 'd'
 | |
|         res = platform.win32_ver(release1, version1, csd1, ptype1)
 | |
|         self.assertEqual(len(res), 4)
 | |
|         release, version, csd, ptype = res
 | |
|         if release:
 | |
|             # Currently, release names always come from internal dicts,
 | |
|             # but this could change over time. For now, we just check that
 | |
|             # release is something different from what we have passed.
 | |
|             self.assertNotEqual(release, release1)
 | |
|         if version:
 | |
|             # It is rather hard to test explicit version without
 | |
|             # going deep into the details.
 | |
|             self.assertIn('.', version)
 | |
|             for v in version.split('.'):
 | |
|                 int(v)  # should not fail
 | |
|         if csd:
 | |
|             self.assertTrue(csd.startswith('SP'), msg=csd)
 | |
|         if ptype:
 | |
|             if os.cpu_count() > 1:
 | |
|                 self.assertIn('Multiprocessor', ptype)
 | |
|             else:
 | |
|                 self.assertIn('Uniprocessor', ptype)
 | |
| 
 | |
|     @unittest.skipIf(support.MS_WINDOWS, 'This test only makes sense on non Windows')
 | |
|     def test_win32_ver_on_non_windows(self):
 | |
|         release, version, csd, ptype = 'a', '1.0', 'c', 'd'
 | |
|         res = platform.win32_ver(release, version, csd, ptype)
 | |
|         self.assertSequenceEqual(res, (release, version, csd, ptype), seq_type=tuple)
 | |
| 
 | |
|     def test_mac_ver(self):
 | |
|         res = platform.mac_ver()
 | |
| 
 | |
|         if platform.uname().system == 'Darwin':
 | |
|             # We are on a macOS system, check that the right version
 | |
|             # information is returned
 | |
|             output = subprocess.check_output(['sw_vers'], text=True)
 | |
|             for line in output.splitlines():
 | |
|                 if line.startswith('ProductVersion:'):
 | |
|                     real_ver = line.strip().split()[-1]
 | |
|                     break
 | |
|             else:
 | |
|                 self.fail(f"failed to parse sw_vers output: {output!r}")
 | |
| 
 | |
|             result_list = res[0].split('.')
 | |
|             expect_list = real_ver.split('.')
 | |
|             len_diff = len(result_list) - len(expect_list)
 | |
|             # On Snow Leopard, sw_vers reports 10.6.0 as 10.6
 | |
|             if len_diff > 0:
 | |
|                 expect_list.extend(['0'] * len_diff)
 | |
|             # For compatibility with older binaries, macOS 11.x may report
 | |
|             # itself as '10.16' rather than '11.x.y'.
 | |
|             if result_list != ['10', '16']:
 | |
|                 self.assertEqual(result_list, expect_list)
 | |
| 
 | |
|             # res[1] claims to contain
 | |
|             # (version, dev_stage, non_release_version)
 | |
|             # That information is no longer available
 | |
|             self.assertEqual(res[1], ('', '', ''))
 | |
| 
 | |
|             if sys.byteorder == 'little':
 | |
|                 self.assertIn(res[2], ('i386', 'x86_64', 'arm64'))
 | |
|             else:
 | |
|                 self.assertEqual(res[2], 'PowerPC')
 | |
| 
 | |
| 
 | |
|     @unittest.skipUnless(sys.platform == 'darwin', "OSX only test")
 | |
|     def test_mac_ver_with_fork(self):
 | |
|         # Issue7895: platform.mac_ver() crashes when using fork without exec
 | |
|         #
 | |
|         # This test checks that the fix for that issue works.
 | |
|         #
 | |
|         pid = os.fork()
 | |
|         if pid == 0:
 | |
|             # child
 | |
|             info = platform.mac_ver()
 | |
|             os._exit(0)
 | |
| 
 | |
|         else:
 | |
|             # parent
 | |
|             support.wait_process(pid, exitcode=0)
 | |
| 
 | |
|     def test_ios_ver(self):
 | |
|         result = platform.ios_ver()
 | |
| 
 | |
|         # ios_ver is only fully available on iOS where ctypes is available.
 | |
|         if sys.platform == "ios" and _ctypes:
 | |
|             system, release, model, is_simulator = result
 | |
|             # Result is a namedtuple
 | |
|             self.assertEqual(result.system, system)
 | |
|             self.assertEqual(result.release, release)
 | |
|             self.assertEqual(result.model, model)
 | |
|             self.assertEqual(result.is_simulator, is_simulator)
 | |
| 
 | |
|             # We can't assert specific values without reproducing the logic of
 | |
|             # ios_ver(), so we check that the values are broadly what we expect.
 | |
| 
 | |
|             # System is either iOS or iPadOS, depending on the test device
 | |
|             self.assertIn(system, {"iOS", "iPadOS"})
 | |
| 
 | |
|             # Release is a numeric version specifier with at least 2 parts
 | |
|             parts = release.split(".")
 | |
|             self.assertGreaterEqual(len(parts), 2)
 | |
|             self.assertTrue(all(part.isdigit() for part in parts))
 | |
| 
 | |
|             # If this is a simulator, we get a high level device descriptor
 | |
|             # with no identifying model number. If this is a physical device,
 | |
|             # we get a model descriptor like "iPhone13,1"
 | |
|             if is_simulator:
 | |
|                 self.assertIn(model, {"iPhone", "iPad"})
 | |
|             else:
 | |
|                 self.assertTrue(
 | |
|                     (model.startswith("iPhone") or model.startswith("iPad"))
 | |
|                     and "," in model
 | |
|                 )
 | |
| 
 | |
|             self.assertEqual(type(is_simulator), bool)
 | |
|         else:
 | |
|             # On non-iOS platforms, calling ios_ver doesn't fail; you get
 | |
|             # default values
 | |
|             self.assertEqual(result.system, "")
 | |
|             self.assertEqual(result.release, "")
 | |
|             self.assertEqual(result.model, "")
 | |
|             self.assertFalse(result.is_simulator)
 | |
| 
 | |
|             # Check the fallback values can be overridden by arguments
 | |
|             override = platform.ios_ver("Foo", "Bar", "Whiz", True)
 | |
|             self.assertEqual(override.system, "Foo")
 | |
|             self.assertEqual(override.release, "Bar")
 | |
|             self.assertEqual(override.model, "Whiz")
 | |
|             self.assertTrue(override.is_simulator)
 | |
| 
 | |
|     @unittest.skipIf(support.is_emscripten, "Does not apply to Emscripten")
 | |
|     def test_libc_ver(self):
 | |
|         # check that libc_ver(executable) doesn't raise an exception
 | |
|         if os.path.isdir(sys.executable) and \
 | |
|            os.path.exists(sys.executable+'.exe'):
 | |
|             # Cygwin horror
 | |
|             executable = sys.executable + '.exe'
 | |
|         elif sys.platform == "win32" and not os.path.exists(sys.executable):
 | |
|             # App symlink appears to not exist, but we want the
 | |
|             # real executable here anyway
 | |
|             import _winapi
 | |
|             executable = _winapi.GetModuleFileName(0)
 | |
|         else:
 | |
|             executable = sys.executable
 | |
|         platform.libc_ver(executable)
 | |
| 
 | |
|         filename = os_helper.TESTFN
 | |
|         self.addCleanup(os_helper.unlink, filename)
 | |
| 
 | |
|         with mock.patch('os.confstr', create=True, return_value='mock 1.0'):
 | |
|             # test os.confstr() code path
 | |
|             self.assertEqual(platform.libc_ver(), ('mock', '1.0'))
 | |
| 
 | |
|             # test the different regular expressions
 | |
|             for data, expected in (
 | |
|                 (b'__libc_init', ('libc', '')),
 | |
|                 (b'GLIBC_2.9', ('glibc', '2.9')),
 | |
|                 (b'libc.so.1.2.5', ('libc', '1.2.5')),
 | |
|                 (b'libc_pthread.so.1.2.5', ('libc', '1.2.5_pthread')),
 | |
|                 (b'', ('', '')),
 | |
|             ):
 | |
|                 with open(filename, 'wb') as fp:
 | |
|                     fp.write(b'[xxx%sxxx]' % data)
 | |
|                     fp.flush()
 | |
| 
 | |
|                 # os.confstr() must not be used if executable is set
 | |
|                 self.assertEqual(platform.libc_ver(executable=filename),
 | |
|                                  expected)
 | |
| 
 | |
|         # binary containing multiple versions: get the most recent,
 | |
|         # make sure that 1.9 is seen as older than 1.23.4
 | |
|         chunksize = 16384
 | |
|         with open(filename, 'wb') as f:
 | |
|             # test match at chunk boundary
 | |
|             f.write(b'x'*(chunksize - 10))
 | |
|             f.write(b'GLIBC_1.23.4\0GLIBC_1.9\0GLIBC_1.21\0')
 | |
|         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
 | |
|         self.assertEqual(V('1.2.3'), V('1.2.3'))
 | |
|         self.assertLess(V('1.2.3'), V('1.2.10'))
 | |
|         self.assertEqual(V('1.2.3.4'), V('1_2-3+4'))
 | |
|         self.assertLess(V('1.2spam'), V('1.2dev'))
 | |
|         self.assertLess(V('1.2dev'), V('1.2alpha'))
 | |
|         self.assertLess(V('1.2dev'), V('1.2a'))
 | |
|         self.assertLess(V('1.2alpha'), V('1.2beta'))
 | |
|         self.assertLess(V('1.2a'), V('1.2b'))
 | |
|         self.assertLess(V('1.2beta'), V('1.2c'))
 | |
|         self.assertLess(V('1.2b'), V('1.2c'))
 | |
|         self.assertLess(V('1.2c'), V('1.2RC'))
 | |
|         self.assertLess(V('1.2c'), V('1.2rc'))
 | |
|         self.assertLess(V('1.2RC'), V('1.2.0'))
 | |
|         self.assertLess(V('1.2rc'), V('1.2.0'))
 | |
|         self.assertLess(V('1.2.0'), V('1.2pl'))
 | |
|         self.assertLess(V('1.2.0'), V('1.2p'))
 | |
| 
 | |
|         self.assertLess(V('1.5.1'), V('1.5.2b2'))
 | |
|         self.assertLess(V('3.10a'), V('161'))
 | |
|         self.assertEqual(V('8.02'), V('8.02'))
 | |
|         self.assertLess(V('3.4j'), V('1996.07.12'))
 | |
|         self.assertLess(V('3.1.1.6'), V('3.2.pl0'))
 | |
|         self.assertLess(V('2g6'), V('11g'))
 | |
|         self.assertLess(V('0.9'), V('2.2'))
 | |
|         self.assertLess(V('1.2'), V('1.2.1'))
 | |
|         self.assertLess(V('1.1'), V('1.2.2'))
 | |
|         self.assertLess(V('1.1'), V('1.2'))
 | |
|         self.assertLess(V('1.2.1'), V('1.2.2'))
 | |
|         self.assertLess(V('1.2'), V('1.2.2'))
 | |
|         self.assertLess(V('0.4'), V('0.4.0'))
 | |
|         self.assertLess(V('1.13++'), V('5.5.kw'))
 | |
|         self.assertLess(V('0.960923'), V('2.2beta29'))
 | |
| 
 | |
| 
 | |
|     def test_macos(self):
 | |
|         self.addCleanup(self.clear_caches)
 | |
| 
 | |
|         uname = ('Darwin', 'hostname', '17.7.0',
 | |
|                  ('Darwin Kernel Version 17.7.0: '
 | |
|                   'Thu Jun 21 22:53:14 PDT 2018; '
 | |
|                   'root:xnu-4570.71.2~1/RELEASE_X86_64'),
 | |
|                  'x86_64', 'i386')
 | |
|         arch = ('64bit', '')
 | |
|         with mock.patch.object(sys, "platform", "darwin"), \
 | |
|              mock.patch.object(platform, 'uname', return_value=uname), \
 | |
|              mock.patch.object(platform, 'architecture', return_value=arch):
 | |
|             for mac_ver, expected_terse, expected in [
 | |
|                 # darwin: mac_ver() returns empty strings
 | |
|                 (('', '', ''),
 | |
|                  'Darwin-17.7.0',
 | |
|                  'Darwin-17.7.0-x86_64-i386-64bit'),
 | |
|                 # macOS: mac_ver() returns macOS version
 | |
|                 (('10.13.6', ('', '', ''), 'x86_64'),
 | |
|                  'macOS-10.13.6',
 | |
|                  'macOS-10.13.6-x86_64-i386-64bit'),
 | |
|             ]:
 | |
|                 with mock.patch.object(platform, 'mac_ver',
 | |
|                                        return_value=mac_ver):
 | |
|                     self.clear_caches()
 | |
|                     self.assertEqual(platform.platform(terse=1), expected_terse)
 | |
|                     self.assertEqual(platform.platform(), expected)
 | |
| 
 | |
|     def test_freedesktop_os_release(self):
 | |
|         self.addCleanup(self.clear_caches)
 | |
|         self.clear_caches()
 | |
| 
 | |
|         if any(os.path.isfile(fn) for fn in platform._os_release_candidates):
 | |
|             info = platform.freedesktop_os_release()
 | |
|             self.assertIn("NAME", info)
 | |
|             self.assertIn("ID", info)
 | |
| 
 | |
|             info["CPYTHON_TEST"] = "test"
 | |
|             self.assertNotIn(
 | |
|                 "CPYTHON_TEST",
 | |
|                 platform.freedesktop_os_release()
 | |
|             )
 | |
|         else:
 | |
|             with self.assertRaises(OSError):
 | |
|                 platform.freedesktop_os_release()
 | |
| 
 | |
|     def test_parse_os_release(self):
 | |
|         info = platform._parse_os_release(FEDORA_OS_RELEASE.splitlines())
 | |
|         self.assertEqual(info["NAME"], "Fedora")
 | |
|         self.assertEqual(info["ID"], "fedora")
 | |
|         self.assertNotIn("ID_LIKE", info)
 | |
|         self.assertEqual(info["VERSION_CODENAME"], "")
 | |
| 
 | |
|         info = platform._parse_os_release(UBUNTU_OS_RELEASE.splitlines())
 | |
|         self.assertEqual(info["NAME"], "Ubuntu")
 | |
|         self.assertEqual(info["ID"], "ubuntu")
 | |
|         self.assertEqual(info["ID_LIKE"], "debian")
 | |
|         self.assertEqual(info["VERSION_CODENAME"], "focal")
 | |
| 
 | |
|         info = platform._parse_os_release(TEST_OS_RELEASE.splitlines())
 | |
|         expected = {
 | |
|             "ID": "linux",
 | |
|             "NAME": "Linux",
 | |
|             "PRETTY_NAME": "Linux",
 | |
|             "ID_LIKE": "egg spam viking",
 | |
|             "EMPTY": "",
 | |
|             "DOUBLE_QUOTE": "double",
 | |
|             "EMPTY_DOUBLE": "",
 | |
|             "SINGLE_QUOTE": "single",
 | |
|             "EMPTY_SINGLE": "",
 | |
|             "QUOTES": "double's",
 | |
|             "SPECIALS": "$`\\'\"",
 | |
|         }
 | |
|         self.assertEqual(info, expected)
 | |
|         self.assertEqual(len(info["SPECIALS"]), 5)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest.main()
 |