blob: ea6752b61d8f77f165c16e76c96c88cc3971f6a1 [file] [log] [blame]
Victor Stinner620c48b2013-12-09 00:01:27 +01001from unittest import mock
Benjamin Peterson856ff5f2008-05-29 21:22:40 +00002import os
Walter Dörwaldc69d1c42005-11-21 17:48:12 +00003import platform
Hirokazu Yamamotoe6748402008-10-06 04:51:11 +00004import subprocess
Victor Stinner3a38a6d2011-06-10 13:59:59 +02005import sys
Victor Stinner620c48b2013-12-09 00:01:27 +01006import tempfile
Victor Stinner3a38a6d2011-06-10 13:59:59 +02007import unittest
8import warnings
Walter Dörwaldc69d1c42005-11-21 17:48:12 +00009
Benjamin Petersonee8712c2008-05-20 21:35:26 +000010from test import support
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +000011
Walter Dörwaldc69d1c42005-11-21 17:48:12 +000012class PlatformTest(unittest.TestCase):
13 def test_architecture(self):
14 res = platform.architecture()
15
Brian Curtin3b4499c2010-12-28 14:31:47 +000016 @support.skip_unless_symlink
Brian Curtind40e6f72010-07-08 21:39:08 +000017 def test_architecture_via_symlink(self): # issue3762
Steve Dower109bc3a2016-09-10 12:19:42 -070018 # 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.
Brian Curtind40e6f72010-07-08 21:39:08 +000020 if sys.platform == "win32":
Victor Stinner0fc55a22016-09-10 06:24:47 -040021 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
Brian Curtin74e45612010-07-09 15:58:59 +000027 os.environ["Path"] = "{};{}".format(
28 os.path.dirname(sys.executable), os.environ["Path"])
Steve Dower109bc3a2016-09-10 12:19:42 -070029 os.environ["PYTHONPATH"] = os.path.dirname(sys.executable)
Brian Curtind40e6f72010-07-08 21:39:08 +000030
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()
Victor Stinner0fc55a22016-09-10 06:24:47 -040036
Brian Curtind40e6f72010-07-08 21:39:08 +000037 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)
Hirokazu Yamamotoe6748402008-10-06 04:51:11 +000044
Walter Dörwaldc69d1c42005-11-21 17:48:12 +000045 def test_platform(self):
46 for aliased in (False, True):
47 for terse in (False, True):
48 res = platform.platform(aliased, terse)
49
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +000050 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
Walter Dörwaldc69d1c42005-11-21 17:48:12 +000065 def test_processor(self):
66 res = platform.processor()
67
Benjamin Petersone549ead2009-03-28 21:42:05 +000068 def setUp(self):
69 self.save_version = sys.version
Ned Deily95c50e52017-03-04 01:05:06 -050070 self.save_git = sys._git
Benjamin Petersone549ead2009-03-28 21:42:05 +000071 self.save_platform = sys.platform
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +000072
Benjamin Petersone549ead2009-03-28 21:42:05 +000073 def tearDown(self):
74 sys.version = self.save_version
Ned Deily95c50e52017-03-04 01:05:06 -050075 sys._git = self.save_git
Benjamin Petersone549ead2009-03-28 21:42:05 +000076 sys.platform = self.save_platform
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +000077
Benjamin Petersone549ead2009-03-28 21:42:05 +000078 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')),
Martin Panter4e505532016-06-08 06:12:22 +000087 ('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')),
Benjamin Petersone549ead2009-03-28 21:42:05 +0000103 ):
104 # branch and revision are not "parsed", but fetched
Ned Deily95c50e52017-03-04 01:05:06 -0500105 # from sys._git. Ignore them
Benjamin Petersone549ead2009-03-28 21:42:05 +0000106 (name, version, branch, revision, buildno, builddate, compiler) \
107 = platform._sys_version(input)
108 self.assertEqual(
109 (name, version, '', '', buildno, builddate, compiler), output)
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +0000110
Benjamin Petersone549ead2009-03-28 21:42:05 +0000111 # 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)'),
Ezio Melottif076f532013-10-21 03:03:32 +0300120
Benjamin Petersone549ead2009-03-28 21:42:05 +0000121 ("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"),
Ezio Melottif076f532013-10-21 03:03:32 +0300125
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
Benjamin Petersone549ead2009-03-28 21:42:05 +0000136 ("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"),
Ezio Melottif076f532013-10-21 03:03:32 +0300141
Benjamin Petersone549ead2009-03-28 21:42:05 +0000142 ("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:
Ned Deily95c50e52017-03-04 01:05:06 -0500152 if hasattr(sys, "_git"):
153 del sys._git
Benjamin Petersone549ead2009-03-28 21:42:05 +0000154 else:
Ned Deily95c50e52017-03-04 01:05:06 -0500155 sys._git = subversion
Benjamin Petersone549ead2009-03-28 21:42:05 +0000156 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])
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000164
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000165 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()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000174 self.assertTrue(any(res))
Larry Hastings68386bc2012-06-24 14:30:41 -0700175 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)
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000181
R. David Murrayca2edce2010-03-22 17:48:48 +0000182 @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:
R. David Murraya1135542010-03-24 00:29:21 +0000189 with support.EnvironmentVarGuard() as environ:
R. David Murrayca2edce2010-03-22 17:48:48 +0000190 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
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000203 def test_java_ver(self):
204 res = platform.java_ver()
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000205 if sys.platform == 'java':
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000206 self.assertTrue(all(res))
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000207
208 def test_win32_ver(self):
209 res = platform.win32_ver()
210
211 def test_mac_ver(self):
212 res = platform.mac_ver()
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000213
Larry Hastings68386bc2012-06-24 14:30:41 -0700214 if platform.uname().system == 'Darwin':
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000215 # 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()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000224 self.assertFalse(real_ver is None)
Brett Cannon353411d2009-09-03 21:29:20 +0000225 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)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000231 self.assertEqual(result_list, expect_list)
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000232
233 # res[1] claims to contain
234 # (version, dev_stage, non_release_version)
235 # That information is no longer available
Ezio Melottib3aedd42010-11-20 19:04:17 +0000236 self.assertEqual(res[1], ('', '', ''))
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000237
238 if sys.byteorder == 'little':
Ned Deily58e33502011-07-13 15:07:04 -0700239 self.assertIn(res[2], ('i386', 'x86_64'))
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000240 else:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000241 self.assertEqual(res[2], 'PowerPC')
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000242
Ronald Oussorene186e382010-07-23 11:54:59 +0000243
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)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000259 self.assertEqual(cpid, pid)
260 self.assertEqual(sts, 0)
Ronald Oussorene186e382010-07-23 11:54:59 +0000261
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000262 def test_dist(self):
Berker Peksag9e7990a2015-05-16 23:21:26 +0300263 with warnings.catch_warnings():
264 warnings.filterwarnings(
265 'ignore',
R David Murray44b548d2016-09-08 13:59:53 -0400266 r'dist\(\) and linux_distribution\(\) '
Berker Peksag9e7990a2015-05-16 23:21:26 +0300267 'functions are deprecated .*',
268 PendingDeprecationWarning,
269 )
270 res = platform.dist()
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000271
272 def test_libc_ver(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000273 import os
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000274 if os.path.isdir(sys.executable) and \
275 os.path.exists(sys.executable+'.exe'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000276 # Cygwin horror
Georg Brandl89fad142010-03-14 10:23:39 +0000277 executable = sys.executable + '.exe'
278 else:
279 executable = sys.executable
280 res = platform.libc_ver(executable)
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000281
Benjamin Peterson1a6e0d02008-10-25 15:49:17 +0000282 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')),
Benjamin Peterson25001472010-01-25 03:37:42 +0000295 ('', ('', '', '')), # If there's nothing there.
Benjamin Peterson1a6e0d02008-10-25 15:49:17 +0000296 ):
297 self.assertEqual(platform._parse_release_file(input), output)
298
Victor Stinner1dfd3802011-03-03 12:54:07 +0000299 def test_popen(self):
Victor Stinnerff45fed2011-03-03 14:07:21 +0000300 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)
Victor Stinner3a38a6d2011-06-10 13:59:59 +0200306 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")
Victor Stinner1dfd3802011-03-03 12:54:07 +0000312
Victor Stinner1dfd3802011-03-03 12:54:07 +0000313 data = 'plop'
Victor Stinnerff45fed2011-03-03 14:07:21 +0000314 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)
Victor Stinner3a38a6d2011-06-10 13:59:59 +0200319 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))
Victor Stinner1dfd3802011-03-03 12:54:07 +0000330
Victor Stinner620c48b2013-12-09 00:01:27 +0100331 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):
Berker Peksag9e7990a2015-05-16 23:21:26 +0300339 with warnings.catch_warnings():
340 warnings.filterwarnings(
341 'ignore',
R David Murray44b548d2016-09-08 13:59:53 -0400342 r'dist\(\) and linux_distribution\(\) '
Berker Peksag9e7990a2015-05-16 23:21:26 +0300343 'functions are deprecated .*',
344 PendingDeprecationWarning,
345 )
346 distname, version, distid = platform.linux_distribution()
Victor Stinner620c48b2013-12-09 00:01:27 +0100347
Barry Warsaw7c549c42014-08-05 11:28:12 -0400348 self.assertEqual(distname, 'Fedora')
Victor Stinner620c48b2013-12-09 00:01:27 +0100349 self.assertEqual(version, '19')
350 self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat')
Benjamin Peterson1a6e0d02008-10-25 15:49:17 +0000351
Berker Peksag2f3742b2015-05-13 12:32:20 +0300352
353class 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 '
Berker Peksag8d8221f2016-04-24 03:32:24 +0300360 'deprecated in Python 3.5')
Berker Peksag2f3742b2015-05-13 12:32:20 +0300361
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 '
Berker Peksag8d8221f2016-04-24 03:32:24 +0300367 'deprecated in Python 3.5')
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000368
369if __name__ == '__main__':
Berker Peksag2f3742b2015-05-13 12:32:20 +0300370 unittest.main()