blob: ed18773326a7ea52cb38e16dd46c6834a2ef1468 [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
18 # On Windows, the EXE needs to know where pythonXY.dll is at so we have
19 # to add the directory to the path.
20 if sys.platform == "win32":
Brian Curtin74e45612010-07-09 15:58:59 +000021 os.environ["Path"] = "{};{}".format(
22 os.path.dirname(sys.executable), os.environ["Path"])
Brian Curtind40e6f72010-07-08 21:39:08 +000023
24 def get(python):
25 cmd = [python, '-c',
26 'import platform; print(platform.architecture())']
27 p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
28 return p.communicate()
29 real = os.path.realpath(sys.executable)
30 link = os.path.abspath(support.TESTFN)
31 os.symlink(real, link)
32 try:
33 self.assertEqual(get(real), get(link))
34 finally:
35 os.remove(link)
Hirokazu Yamamotoe6748402008-10-06 04:51:11 +000036
Walter Dörwaldc69d1c42005-11-21 17:48:12 +000037 def test_platform(self):
38 for aliased in (False, True):
39 for terse in (False, True):
40 res = platform.platform(aliased, terse)
41
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +000042 def test_system(self):
43 res = platform.system()
44
45 def test_node(self):
46 res = platform.node()
47
48 def test_release(self):
49 res = platform.release()
50
51 def test_version(self):
52 res = platform.version()
53
54 def test_machine(self):
55 res = platform.machine()
56
Walter Dörwaldc69d1c42005-11-21 17:48:12 +000057 def test_processor(self):
58 res = platform.processor()
59
Benjamin Petersone549ead2009-03-28 21:42:05 +000060 def setUp(self):
61 self.save_version = sys.version
Georg Brandl82562422011-03-05 21:09:22 +010062 self.save_mercurial = sys._mercurial
Benjamin Petersone549ead2009-03-28 21:42:05 +000063 self.save_platform = sys.platform
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +000064
Benjamin Petersone549ead2009-03-28 21:42:05 +000065 def tearDown(self):
66 sys.version = self.save_version
Georg Brandl82562422011-03-05 21:09:22 +010067 sys._mercurial = self.save_mercurial
Benjamin Petersone549ead2009-03-28 21:42:05 +000068 sys.platform = self.save_platform
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +000069
Benjamin Petersone549ead2009-03-28 21:42:05 +000070 def test_sys_version(self):
71 # Old test.
72 for input, output in (
73 ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]',
74 ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')),
75 ('IronPython 1.0.60816 on .NET 2.0.50727.42',
76 ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')),
77 ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42',
78 ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')),
Martin Panter4e505532016-06-08 06:12:22 +000079 ('2.4.3 (truncation, date, t) \n[GCC]',
80 ('CPython', '2.4.3', '', '', 'truncation', 'date t', 'GCC')),
81 ('2.4.3 (truncation, date, ) \n[GCC]',
82 ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
83 ('2.4.3 (truncation, date,) \n[GCC]',
84 ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
85 ('2.4.3 (truncation, date) \n[GCC]',
86 ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
87 ('2.4.3 (truncation, d) \n[GCC]',
88 ('CPython', '2.4.3', '', '', 'truncation', 'd', 'GCC')),
89 ('2.4.3 (truncation, ) \n[GCC]',
90 ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
91 ('2.4.3 (truncation,) \n[GCC]',
92 ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
93 ('2.4.3 (truncation) \n[GCC]',
94 ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
Benjamin Petersone549ead2009-03-28 21:42:05 +000095 ):
96 # branch and revision are not "parsed", but fetched
Georg Brandl776e5862011-03-06 10:35:42 +010097 # from sys._mercurial. Ignore them
Benjamin Petersone549ead2009-03-28 21:42:05 +000098 (name, version, branch, revision, buildno, builddate, compiler) \
99 = platform._sys_version(input)
100 self.assertEqual(
101 (name, version, '', '', buildno, builddate, compiler), output)
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +0000102
Benjamin Petersone549ead2009-03-28 21:42:05 +0000103 # Tests for python_implementation(), python_version(), python_branch(),
104 # python_revision(), python_build(), and python_compiler().
105 sys_versions = {
106 ("2.6.1 (r261:67515, Dec 6 2008, 15:26:00) \n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]",
107 ('CPython', 'tags/r261', '67515'), self.save_platform)
108 :
109 ("CPython", "2.6.1", "tags/r261", "67515",
110 ('r261:67515', 'Dec 6 2008 15:26:00'),
111 'GCC 4.0.1 (Apple Computer, Inc. build 5370)'),
Ezio Melottif076f532013-10-21 03:03:32 +0300112
Benjamin Petersone549ead2009-03-28 21:42:05 +0000113 ("IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053", None, "cli")
114 :
115 ("IronPython", "2.0.0", "", "", ("", ""),
116 ".NET 2.0.50727.3053"),
Ezio Melottif076f532013-10-21 03:03:32 +0300117
118 ("2.6.1 (IronPython 2.6.1 (2.6.10920.0) on .NET 2.0.50727.1433)", None, "cli")
119 :
120 ("IronPython", "2.6.1", "", "", ("", ""),
121 ".NET 2.0.50727.1433"),
122
123 ("2.7.4 (IronPython 2.7.4 (2.7.0.40) on Mono 4.0.30319.1 (32-bit))", None, "cli")
124 :
125 ("IronPython", "2.7.4", "", "", ("", ""),
126 "Mono 4.0.30319.1 (32-bit)"),
127
Benjamin Petersone549ead2009-03-28 21:42:05 +0000128 ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]",
129 ('Jython', 'trunk', '6107'), "java1.5.0_16")
130 :
131 ("Jython", "2.5.0", "trunk", "6107",
132 ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"),
Ezio Melottif076f532013-10-21 03:03:32 +0300133
Benjamin Petersone549ead2009-03-28 21:42:05 +0000134 ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]",
135 ('PyPy', 'trunk', '63378'), self.save_platform)
136 :
137 ("PyPy", "2.5.2", "trunk", "63378", ('63378', 'Mar 26 2009'),
138 "")
139 }
140 for (version_tag, subversion, sys_platform), info in \
141 sys_versions.items():
142 sys.version = version_tag
143 if subversion is None:
Georg Brandl82562422011-03-05 21:09:22 +0100144 if hasattr(sys, "_mercurial"):
145 del sys._mercurial
Benjamin Petersone549ead2009-03-28 21:42:05 +0000146 else:
Georg Brandl82562422011-03-05 21:09:22 +0100147 sys._mercurial = subversion
Benjamin Petersone549ead2009-03-28 21:42:05 +0000148 if sys_platform is not None:
149 sys.platform = sys_platform
150 self.assertEqual(platform.python_implementation(), info[0])
151 self.assertEqual(platform.python_version(), info[1])
152 self.assertEqual(platform.python_branch(), info[2])
153 self.assertEqual(platform.python_revision(), info[3])
154 self.assertEqual(platform.python_build(), info[4])
155 self.assertEqual(platform.python_compiler(), info[5])
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000156
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000157 def test_system_alias(self):
158 res = platform.system_alias(
159 platform.system(),
160 platform.release(),
161 platform.version(),
162 )
163
164 def test_uname(self):
165 res = platform.uname()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000166 self.assertTrue(any(res))
Larry Hastings68386bc2012-06-24 14:30:41 -0700167 self.assertEqual(res[0], res.system)
168 self.assertEqual(res[1], res.node)
169 self.assertEqual(res[2], res.release)
170 self.assertEqual(res[3], res.version)
171 self.assertEqual(res[4], res.machine)
172 self.assertEqual(res[5], res.processor)
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000173
R. David Murrayca2edce2010-03-22 17:48:48 +0000174 @unittest.skipUnless(sys.platform.startswith('win'), "windows only test")
175 def test_uname_win32_ARCHITEW6432(self):
176 # Issue 7860: make sure we get architecture from the correct variable
177 # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be
178 # using it, per
179 # http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx
180 try:
R. David Murraya1135542010-03-24 00:29:21 +0000181 with support.EnvironmentVarGuard() as environ:
R. David Murrayca2edce2010-03-22 17:48:48 +0000182 if 'PROCESSOR_ARCHITEW6432' in environ:
183 del environ['PROCESSOR_ARCHITEW6432']
184 environ['PROCESSOR_ARCHITECTURE'] = 'foo'
185 platform._uname_cache = None
186 system, node, release, version, machine, processor = platform.uname()
187 self.assertEqual(machine, 'foo')
188 environ['PROCESSOR_ARCHITEW6432'] = 'bar'
189 platform._uname_cache = None
190 system, node, release, version, machine, processor = platform.uname()
191 self.assertEqual(machine, 'bar')
192 finally:
193 platform._uname_cache = None
194
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000195 def test_java_ver(self):
196 res = platform.java_ver()
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000197 if sys.platform == 'java':
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000198 self.assertTrue(all(res))
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000199
200 def test_win32_ver(self):
201 res = platform.win32_ver()
202
203 def test_mac_ver(self):
204 res = platform.mac_ver()
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000205
Larry Hastings68386bc2012-06-24 14:30:41 -0700206 if platform.uname().system == 'Darwin':
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000207 # We're on a MacOSX system, check that
208 # the right version information is returned
209 fd = os.popen('sw_vers', 'r')
210 real_ver = None
211 for ln in fd:
212 if ln.startswith('ProductVersion:'):
213 real_ver = ln.strip().split()[-1]
214 break
215 fd.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000216 self.assertFalse(real_ver is None)
Brett Cannon353411d2009-09-03 21:29:20 +0000217 result_list = res[0].split('.')
218 expect_list = real_ver.split('.')
219 len_diff = len(result_list) - len(expect_list)
220 # On Snow Leopard, sw_vers reports 10.6.0 as 10.6
221 if len_diff > 0:
222 expect_list.extend(['0'] * len_diff)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000223 self.assertEqual(result_list, expect_list)
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000224
225 # res[1] claims to contain
226 # (version, dev_stage, non_release_version)
227 # That information is no longer available
Ezio Melottib3aedd42010-11-20 19:04:17 +0000228 self.assertEqual(res[1], ('', '', ''))
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000229
230 if sys.byteorder == 'little':
Ned Deily58e33502011-07-13 15:07:04 -0700231 self.assertIn(res[2], ('i386', 'x86_64'))
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000232 else:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000233 self.assertEqual(res[2], 'PowerPC')
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000234
Ronald Oussorene186e382010-07-23 11:54:59 +0000235
236 @unittest.skipUnless(sys.platform == 'darwin', "OSX only test")
237 def test_mac_ver_with_fork(self):
238 # Issue7895: platform.mac_ver() crashes when using fork without exec
239 #
240 # This test checks that the fix for that issue works.
241 #
242 pid = os.fork()
243 if pid == 0:
244 # child
245 info = platform.mac_ver()
246 os._exit(0)
247
248 else:
249 # parent
250 cpid, sts = os.waitpid(pid, 0)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000251 self.assertEqual(cpid, pid)
252 self.assertEqual(sts, 0)
Ronald Oussorene186e382010-07-23 11:54:59 +0000253
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000254 def test_dist(self):
Berker Peksag9e7990a2015-05-16 23:21:26 +0300255 with warnings.catch_warnings():
256 warnings.filterwarnings(
257 'ignore',
258 'dist\(\) and linux_distribution\(\) '
259 'functions are deprecated .*',
260 PendingDeprecationWarning,
261 )
262 res = platform.dist()
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000263
264 def test_libc_ver(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000265 import os
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000266 if os.path.isdir(sys.executable) and \
267 os.path.exists(sys.executable+'.exe'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000268 # Cygwin horror
Georg Brandl89fad142010-03-14 10:23:39 +0000269 executable = sys.executable + '.exe'
270 else:
271 executable = sys.executable
272 res = platform.libc_ver(executable)
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000273
Benjamin Peterson1a6e0d02008-10-25 15:49:17 +0000274 def test_parse_release_file(self):
275
276 for input, output in (
277 # Examples of release file contents:
278 ('SuSE Linux 9.3 (x86-64)', ('SuSE Linux ', '9.3', 'x86-64')),
279 ('SUSE LINUX 10.1 (X86-64)', ('SUSE LINUX ', '10.1', 'X86-64')),
280 ('SUSE LINUX 10.1 (i586)', ('SUSE LINUX ', '10.1', 'i586')),
281 ('Fedora Core release 5 (Bordeaux)', ('Fedora Core', '5', 'Bordeaux')),
282 ('Red Hat Linux release 8.0 (Psyche)', ('Red Hat Linux', '8.0', 'Psyche')),
283 ('Red Hat Linux release 9 (Shrike)', ('Red Hat Linux', '9', 'Shrike')),
284 ('Red Hat Enterprise Linux release 4 (Nahant)', ('Red Hat Enterprise Linux', '4', 'Nahant')),
285 ('CentOS release 4', ('CentOS', '4', None)),
286 ('Rocks release 4.2.1 (Cydonia)', ('Rocks', '4.2.1', 'Cydonia')),
Benjamin Peterson25001472010-01-25 03:37:42 +0000287 ('', ('', '', '')), # If there's nothing there.
Benjamin Peterson1a6e0d02008-10-25 15:49:17 +0000288 ):
289 self.assertEqual(platform._parse_release_file(input), output)
290
Victor Stinner1dfd3802011-03-03 12:54:07 +0000291 def test_popen(self):
Victor Stinnerff45fed2011-03-03 14:07:21 +0000292 mswindows = (sys.platform == "win32")
293
294 if mswindows:
295 command = '"{}" -c "print(\'Hello\')"'.format(sys.executable)
296 else:
297 command = "'{}' -c 'print(\"Hello\")'".format(sys.executable)
Victor Stinner3a38a6d2011-06-10 13:59:59 +0200298 with warnings.catch_warnings():
299 warnings.simplefilter("ignore", DeprecationWarning)
300 with platform.popen(command) as stdout:
301 hello = stdout.read().strip()
302 stdout.close()
303 self.assertEqual(hello, "Hello")
Victor Stinner1dfd3802011-03-03 12:54:07 +0000304
Victor Stinner1dfd3802011-03-03 12:54:07 +0000305 data = 'plop'
Victor Stinnerff45fed2011-03-03 14:07:21 +0000306 if mswindows:
307 command = '"{}" -c "import sys; data=sys.stdin.read(); exit(len(data))"'
308 else:
309 command = "'{}' -c 'import sys; data=sys.stdin.read(); exit(len(data))'"
310 command = command.format(sys.executable)
Victor Stinner3a38a6d2011-06-10 13:59:59 +0200311 with warnings.catch_warnings():
312 warnings.simplefilter("ignore", DeprecationWarning)
313 with platform.popen(command, 'w') as stdin:
314 stdout = stdin.write(data)
315 ret = stdin.close()
316 self.assertIsNotNone(ret)
317 if os.name == 'nt':
318 returncode = ret
319 else:
320 returncode = ret >> 8
321 self.assertEqual(returncode, len(data))
Victor Stinner1dfd3802011-03-03 12:54:07 +0000322
Victor Stinner620c48b2013-12-09 00:01:27 +0100323 def test_linux_distribution_encoding(self):
324 # Issue #17429
325 with tempfile.TemporaryDirectory() as tempdir:
326 filename = os.path.join(tempdir, 'fedora-release')
327 with open(filename, 'w', encoding='utf-8') as f:
328 f.write('Fedora release 19 (Schr\xf6dinger\u2019s Cat)\n')
329
330 with mock.patch('platform._UNIXCONFDIR', tempdir):
Berker Peksag9e7990a2015-05-16 23:21:26 +0300331 with warnings.catch_warnings():
332 warnings.filterwarnings(
333 'ignore',
334 'dist\(\) and linux_distribution\(\) '
335 'functions are deprecated .*',
336 PendingDeprecationWarning,
337 )
338 distname, version, distid = platform.linux_distribution()
Victor Stinner620c48b2013-12-09 00:01:27 +0100339
Barry Warsaw7c549c42014-08-05 11:28:12 -0400340 self.assertEqual(distname, 'Fedora')
Victor Stinner620c48b2013-12-09 00:01:27 +0100341 self.assertEqual(version, '19')
342 self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat')
Benjamin Peterson1a6e0d02008-10-25 15:49:17 +0000343
Berker Peksag2f3742b2015-05-13 12:32:20 +0300344
345class DeprecationTest(unittest.TestCase):
346
347 def test_dist_deprecation(self):
348 with self.assertWarns(PendingDeprecationWarning) as cm:
349 platform.dist()
350 self.assertEqual(str(cm.warning),
351 'dist() and linux_distribution() functions are '
Berker Peksag8d8221f2016-04-24 03:32:24 +0300352 'deprecated in Python 3.5')
Berker Peksag2f3742b2015-05-13 12:32:20 +0300353
354 def test_linux_distribution_deprecation(self):
355 with self.assertWarns(PendingDeprecationWarning) as cm:
356 platform.linux_distribution()
357 self.assertEqual(str(cm.warning),
358 'dist() and linux_distribution() functions are '
Berker Peksag8d8221f2016-04-24 03:32:24 +0300359 'deprecated in Python 3.5')
Walter Dörwaldc69d1c42005-11-21 17:48:12 +0000360
361if __name__ == '__main__':
Berker Peksag2f3742b2015-05-13 12:32:20 +0300362 unittest.main()