1 from unittest import mock 2 import os 3 import platform 4 import subprocess 5 import sys 6 import tempfile 7 import unittest 8 import warnings 9 10 from test import support 11 12 class PlatformTest(unittest.TestCase): 13 def test_architecture(self): 14 res = platform.architecture() 15 16 @support.skip_unless_symlink 17 def test_architecture_via_symlink(self): # issue3762 18 # On Windows, the EXE needs to know where pythonXY.dll and *.pyd is at 19 # so we add the directory to the path and PYTHONPATH. 20 if sys.platform == "win32": 21 def restore_environ(old_env): 22 os.environ.clear() 23 os.environ.update(old_env) 24 25 self.addCleanup(restore_environ, dict(os.environ)) 26 27 os.environ["Path"] = "{};{}".format( 28 os.path.dirname(sys.executable), os.environ["Path"]) 29 os.environ["PYTHONPATH"] = os.path.dirname(sys.executable) 30 31 def get(python): 32 cmd = [python, '-c', 33 'import platform; print(platform.architecture())'] 34 p = subprocess.Popen(cmd, stdout=subprocess.PIPE) 35 return p.communicate() 36 37 real = os.path.realpath(sys.executable) 38 link = os.path.abspath(support.TESTFN) 39 os.symlink(real, link) 40 try: 41 self.assertEqual(get(real), get(link)) 42 finally: 43 os.remove(link) 44 45 def test_platform(self): 46 for aliased in (False, True): 47 for terse in (False, True): 48 res = platform.platform(aliased, terse) 49 50 def test_system(self): 51 res = platform.system() 52 53 def test_node(self): 54 res = platform.node() 55 56 def test_release(self): 57 res = platform.release() 58 59 def test_version(self): 60 res = platform.version() 61 62 def test_machine(self): 63 res = platform.machine() 64 65 def test_processor(self): 66 res = platform.processor() 67 68 def setUp(self): 69 self.save_version = sys.version 70 self.save_git = sys._git 71 self.save_platform = sys.platform 72 73 def tearDown(self): 74 sys.version = self.save_version 75 sys._git = self.save_git 76 sys.platform = self.save_platform 77 78 def test_sys_version(self): 79 # Old test. 80 for input, output in ( 81 ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]', 82 ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')), 83 ('IronPython 1.0.60816 on .NET 2.0.50727.42', 84 ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')), 85 ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42', 86 ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')), 87 ('2.4.3 (truncation, date, t) \n[GCC]', 88 ('CPython', '2.4.3', '', '', 'truncation', 'date t', 'GCC')), 89 ('2.4.3 (truncation, date, ) \n[GCC]', 90 ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')), 91 ('2.4.3 (truncation, date,) \n[GCC]', 92 ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')), 93 ('2.4.3 (truncation, date) \n[GCC]', 94 ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')), 95 ('2.4.3 (truncation, d) \n[GCC]', 96 ('CPython', '2.4.3', '', '', 'truncation', 'd', 'GCC')), 97 ('2.4.3 (truncation, ) \n[GCC]', 98 ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')), 99 ('2.4.3 (truncation,) \n[GCC]', 100 ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')), 101 ('2.4.3 (truncation) \n[GCC]', 102 ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')), 103 ): 104 # branch and revision are not "parsed", but fetched 105 # from sys._git. Ignore them 106 (name, version, branch, revision, buildno, builddate, compiler) \ 107 = platform._sys_version(input) 108 self.assertEqual( 109 (name, version, '', '', buildno, builddate, compiler), output) 110 111 # Tests for python_implementation(), python_version(), python_branch(), 112 # python_revision(), python_build(), and python_compiler(). 113 sys_versions = { 114 ("2.6.1 (r261:67515, Dec 6 2008, 15:26:00) \n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]", 115 ('CPython', 'tags/r261', '67515'), self.save_platform) 116 : 117 ("CPython", "2.6.1", "tags/r261", "67515", 118 ('r261:67515', 'Dec 6 2008 15:26:00'), 119 'GCC 4.0.1 (Apple Computer, Inc. build 5370)'), 120 121 ("IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053", None, "cli") 122 : 123 ("IronPython", "2.0.0", "", "", ("", ""), 124 ".NET 2.0.50727.3053"), 125 126 ("2.6.1 (IronPython 2.6.1 (2.6.10920.0) on .NET 2.0.50727.1433)", None, "cli") 127 : 128 ("IronPython", "2.6.1", "", "", ("", ""), 129 ".NET 2.0.50727.1433"), 130 131 ("2.7.4 (IronPython 2.7.4 (2.7.0.40) on Mono 4.0.30319.1 (32-bit))", None, "cli") 132 : 133 ("IronPython", "2.7.4", "", "", ("", ""), 134 "Mono 4.0.30319.1 (32-bit)"), 135 136 ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]", 137 ('Jython', 'trunk', '6107'), "java1.5.0_16") 138 : 139 ("Jython", "2.5.0", "trunk", "6107", 140 ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"), 141 142 ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]", 143 ('PyPy', 'trunk', '63378'), self.save_platform) 144 : 145 ("PyPy", "2.5.2", "trunk", "63378", ('63378', 'Mar 26 2009'), 146 "") 147 } 148 for (version_tag, subversion, sys_platform), info in \ 149 sys_versions.items(): 150 sys.version = version_tag 151 if subversion is None: 152 if hasattr(sys, "_git"): 153 del sys._git 154 else: 155 sys._git = subversion 156 if sys_platform is not None: 157 sys.platform = sys_platform 158 self.assertEqual(platform.python_implementation(), info[0]) 159 self.assertEqual(platform.python_version(), info[1]) 160 self.assertEqual(platform.python_branch(), info[2]) 161 self.assertEqual(platform.python_revision(), info[3]) 162 self.assertEqual(platform.python_build(), info[4]) 163 self.assertEqual(platform.python_compiler(), info[5]) 164 165 def test_system_alias(self): 166 res = platform.system_alias( 167 platform.system(), 168 platform.release(), 169 platform.version(), 170 ) 171 172 def test_uname(self): 173 res = platform.uname() 174 self.assertTrue(any(res)) 175 self.assertEqual(res[0], res.system) 176 self.assertEqual(res[1], res.node) 177 self.assertEqual(res[2], res.release) 178 self.assertEqual(res[3], res.version) 179 self.assertEqual(res[4], res.machine) 180 self.assertEqual(res[5], res.processor) 181 182 @unittest.skipUnless(sys.platform.startswith('win'), "windows only test") 183 def test_uname_win32_ARCHITEW6432(self): 184 # Issue 7860: make sure we get architecture from the correct variable 185 # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be 186 # using it, per 187 # http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx 188 try: 189 with support.EnvironmentVarGuard() as environ: 190 if 'PROCESSOR_ARCHITEW6432' in environ: 191 del environ['PROCESSOR_ARCHITEW6432'] 192 environ['PROCESSOR_ARCHITECTURE'] = 'foo' 193 platform._uname_cache = None 194 system, node, release, version, machine, processor = platform.uname() 195 self.assertEqual(machine, 'foo') 196 environ['PROCESSOR_ARCHITEW6432'] = 'bar' 197 platform._uname_cache = None 198 system, node, release, version, machine, processor = platform.uname() 199 self.assertEqual(machine, 'bar') 200 finally: 201 platform._uname_cache = None 202 203 def test_java_ver(self): 204 res = platform.java_ver() 205 if sys.platform == 'java': 206 self.assertTrue(all(res)) 207 208 def test_win32_ver(self): 209 res = platform.win32_ver() 210 211 def test_mac_ver(self): 212 res = platform.mac_ver() 213 214 if platform.uname().system == 'Darwin': 215 # We're on a MacOSX system, check that 216 # the right version information is returned 217 fd = os.popen('sw_vers', 'r') 218 real_ver = None 219 for ln in fd: 220 if ln.startswith('ProductVersion:'): 221 real_ver = ln.strip().split()[-1] 222 break 223 fd.close() 224 self.assertFalse(real_ver is None) 225 result_list = res[0].split('.') 226 expect_list = real_ver.split('.') 227 len_diff = len(result_list) - len(expect_list) 228 # On Snow Leopard, sw_vers reports 10.6.0 as 10.6 229 if len_diff > 0: 230 expect_list.extend(['0'] * len_diff) 231 self.assertEqual(result_list, expect_list) 232 233 # res[1] claims to contain 234 # (version, dev_stage, non_release_version) 235 # That information is no longer available 236 self.assertEqual(res[1], ('', '', '')) 237 238 if sys.byteorder == 'little': 239 self.assertIn(res[2], ('i386', 'x86_64')) 240 else: 241 self.assertEqual(res[2], 'PowerPC') 242 243 244 @unittest.skipUnless(sys.platform == 'darwin', "OSX only test") 245 def test_mac_ver_with_fork(self): 246 # Issue7895: platform.mac_ver() crashes when using fork without exec 247 # 248 # This test checks that the fix for that issue works. 249 # 250 pid = os.fork() 251 if pid == 0: 252 # child 253 info = platform.mac_ver() 254 os._exit(0) 255 256 else: 257 # parent 258 cpid, sts = os.waitpid(pid, 0) 259 self.assertEqual(cpid, pid) 260 self.assertEqual(sts, 0) 261 262 def test_dist(self): 263 with warnings.catch_warnings(): 264 warnings.filterwarnings( 265 'ignore', 266 r'dist\(\) and linux_distribution\(\) ' 267 'functions are deprecated .*', 268 PendingDeprecationWarning, 269 ) 270 res = platform.dist() 271 272 def test_libc_ver(self): 273 import os 274 if os.path.isdir(sys.executable) and \ 275 os.path.exists(sys.executable+'.exe'): 276 # Cygwin horror 277 executable = sys.executable + '.exe' 278 else: 279 executable = sys.executable 280 res = platform.libc_ver(executable) 281 282 def test_parse_release_file(self): 283 284 for input, output in ( 285 # Examples of release file contents: 286 ('SuSE Linux 9.3 (x86-64)', ('SuSE Linux ', '9.3', 'x86-64')), 287 ('SUSE LINUX 10.1 (X86-64)', ('SUSE LINUX ', '10.1', 'X86-64')), 288 ('SUSE LINUX 10.1 (i586)', ('SUSE LINUX ', '10.1', 'i586')), 289 ('Fedora Core release 5 (Bordeaux)', ('Fedora Core', '5', 'Bordeaux')), 290 ('Red Hat Linux release 8.0 (Psyche)', ('Red Hat Linux', '8.0', 'Psyche')), 291 ('Red Hat Linux release 9 (Shrike)', ('Red Hat Linux', '9', 'Shrike')), 292 ('Red Hat Enterprise Linux release 4 (Nahant)', ('Red Hat Enterprise Linux', '4', 'Nahant')), 293 ('CentOS release 4', ('CentOS', '4', None)), 294 ('Rocks release 4.2.1 (Cydonia)', ('Rocks', '4.2.1', 'Cydonia')), 295 ('', ('', '', '')), # If there's nothing there. 296 ): 297 self.assertEqual(platform._parse_release_file(input), output) 298 299 def test_popen(self): 300 mswindows = (sys.platform == "win32") 301 302 if mswindows: 303 command = '"{}" -c "print(\'Hello\')"'.format(sys.executable) 304 else: 305 command = "'{}' -c 'print(\"Hello\")'".format(sys.executable) 306 with warnings.catch_warnings(): 307 warnings.simplefilter("ignore", DeprecationWarning) 308 with platform.popen(command) as stdout: 309 hello = stdout.read().strip() 310 stdout.close() 311 self.assertEqual(hello, "Hello") 312 313 data = 'plop' 314 if mswindows: 315 command = '"{}" -c "import sys; data=sys.stdin.read(); exit(len(data))"' 316 else: 317 command = "'{}' -c 'import sys; data=sys.stdin.read(); exit(len(data))'" 318 command = command.format(sys.executable) 319 with warnings.catch_warnings(): 320 warnings.simplefilter("ignore", DeprecationWarning) 321 with platform.popen(command, 'w') as stdin: 322 stdout = stdin.write(data) 323 ret = stdin.close() 324 self.assertIsNotNone(ret) 325 if os.name == 'nt': 326 returncode = ret 327 else: 328 returncode = ret >> 8 329 self.assertEqual(returncode, len(data)) 330 331 def test_linux_distribution_encoding(self): 332 # Issue #17429 333 with tempfile.TemporaryDirectory() as tempdir: 334 filename = os.path.join(tempdir, 'fedora-release') 335 with open(filename, 'w', encoding='utf-8') as f: 336 f.write('Fedora release 19 (Schr\xf6dinger\u2019s Cat)\n') 337 338 with mock.patch('platform._UNIXCONFDIR', tempdir): 339 with warnings.catch_warnings(): 340 warnings.filterwarnings( 341 'ignore', 342 r'dist\(\) and linux_distribution\(\) ' 343 'functions are deprecated .*', 344 PendingDeprecationWarning, 345 ) 346 distname, version, distid = platform.linux_distribution() 347 348 self.assertEqual(distname, 'Fedora') 349 self.assertEqual(version, '19') 350 self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat') 351 352 353 class DeprecationTest(unittest.TestCase): 354 355 def test_dist_deprecation(self): 356 with self.assertWarns(PendingDeprecationWarning) as cm: 357 platform.dist() 358 self.assertEqual(str(cm.warning), 359 'dist() and linux_distribution() functions are ' 360 'deprecated in Python 3.5') 361 362 def test_linux_distribution_deprecation(self): 363 with self.assertWarns(PendingDeprecationWarning) as cm: 364 platform.linux_distribution() 365 self.assertEqual(str(cm.warning), 366 'dist() and linux_distribution() functions are ' 367 'deprecated in Python 3.5') 368 369 if __name__ == '__main__': 370 unittest.main() 371