PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_os.py

https://bitbucket.org/mirror/cpython/
Python | 3191 lines | 2791 code | 223 blank | 177 comment | 217 complexity | 56001d5d1ca67eeff86a0af818a15624 MD5 | raw file
Possible License(s): Unlicense, 0BSD, BSD-3-Clause
  1. # As a test suite for the os module, this is woefully inadequate, but this
  2. # does add tests for a few functions which have been determined to be more
  3. # portable than they had been thought to be.
  4. import asynchat
  5. import asyncore
  6. import codecs
  7. import contextlib
  8. import decimal
  9. import errno
  10. import fractions
  11. import getpass
  12. import itertools
  13. import locale
  14. import mmap
  15. import os
  16. import pickle
  17. import re
  18. import shutil
  19. import signal
  20. import socket
  21. import stat
  22. import subprocess
  23. import sys
  24. import sysconfig
  25. import time
  26. import unittest
  27. import uuid
  28. import warnings
  29. from test import support
  30. try:
  31. import threading
  32. except ImportError:
  33. threading = None
  34. try:
  35. import resource
  36. except ImportError:
  37. resource = None
  38. try:
  39. import fcntl
  40. except ImportError:
  41. fcntl = None
  42. try:
  43. import _winapi
  44. except ImportError:
  45. _winapi = None
  46. try:
  47. import grp
  48. groups = [g.gr_gid for g in grp.getgrall() if getpass.getuser() in g.gr_mem]
  49. if hasattr(os, 'getgid'):
  50. process_gid = os.getgid()
  51. if process_gid not in groups:
  52. groups.append(process_gid)
  53. except ImportError:
  54. groups = []
  55. try:
  56. import pwd
  57. all_users = [u.pw_uid for u in pwd.getpwall()]
  58. except ImportError:
  59. all_users = []
  60. try:
  61. from _testcapi import INT_MAX, PY_SSIZE_T_MAX
  62. except ImportError:
  63. INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
  64. from test.support.script_helper import assert_python_ok
  65. from test.support import unix_shell
  66. root_in_posix = False
  67. if hasattr(os, 'geteuid'):
  68. root_in_posix = (os.geteuid() == 0)
  69. # Detect whether we're on a Linux system that uses the (now outdated
  70. # and unmaintained) linuxthreads threading library. There's an issue
  71. # when combining linuxthreads with a failed execv call: see
  72. # http://bugs.python.org/issue4970.
  73. if hasattr(sys, 'thread_info') and sys.thread_info.version:
  74. USING_LINUXTHREADS = sys.thread_info.version.startswith("linuxthreads")
  75. else:
  76. USING_LINUXTHREADS = False
  77. # Issue #14110: Some tests fail on FreeBSD if the user is in the wheel group.
  78. HAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0
  79. @contextlib.contextmanager
  80. def ignore_deprecation_warnings(msg_regex, quiet=False):
  81. with support.check_warnings((msg_regex, DeprecationWarning), quiet=quiet):
  82. yield
  83. @contextlib.contextmanager
  84. def bytes_filename_warn(expected):
  85. msg = 'The Windows bytes API has been deprecated'
  86. if os.name == 'nt':
  87. with ignore_deprecation_warnings(msg, quiet=not expected):
  88. yield
  89. else:
  90. yield
  91. def create_file(filename, content=b'content'):
  92. with open(filename, "xb", 0) as fp:
  93. fp.write(content)
  94. # Tests creating TESTFN
  95. class FileTests(unittest.TestCase):
  96. def setUp(self):
  97. if os.path.lexists(support.TESTFN):
  98. os.unlink(support.TESTFN)
  99. tearDown = setUp
  100. def test_access(self):
  101. f = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
  102. os.close(f)
  103. self.assertTrue(os.access(support.TESTFN, os.W_OK))
  104. def test_closerange(self):
  105. first = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
  106. # We must allocate two consecutive file descriptors, otherwise
  107. # it will mess up other file descriptors (perhaps even the three
  108. # standard ones).
  109. second = os.dup(first)
  110. try:
  111. retries = 0
  112. while second != first + 1:
  113. os.close(first)
  114. retries += 1
  115. if retries > 10:
  116. # XXX test skipped
  117. self.skipTest("couldn't allocate two consecutive fds")
  118. first, second = second, os.dup(second)
  119. finally:
  120. os.close(second)
  121. # close a fd that is open, and one that isn't
  122. os.closerange(first, first + 2)
  123. self.assertRaises(OSError, os.write, first, b"a")
  124. @support.cpython_only
  125. def test_rename(self):
  126. path = support.TESTFN
  127. old = sys.getrefcount(path)
  128. self.assertRaises(TypeError, os.rename, path, 0)
  129. new = sys.getrefcount(path)
  130. self.assertEqual(old, new)
  131. def test_read(self):
  132. with open(support.TESTFN, "w+b") as fobj:
  133. fobj.write(b"spam")
  134. fobj.flush()
  135. fd = fobj.fileno()
  136. os.lseek(fd, 0, 0)
  137. s = os.read(fd, 4)
  138. self.assertEqual(type(s), bytes)
  139. self.assertEqual(s, b"spam")
  140. @support.cpython_only
  141. # Skip the test on 32-bit platforms: the number of bytes must fit in a
  142. # Py_ssize_t type
  143. @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX,
  144. "needs INT_MAX < PY_SSIZE_T_MAX")
  145. @support.bigmemtest(size=INT_MAX + 10, memuse=1, dry_run=False)
  146. def test_large_read(self, size):
  147. self.addCleanup(support.unlink, support.TESTFN)
  148. create_file(support.TESTFN, b'test')
  149. # Issue #21932: Make sure that os.read() does not raise an
  150. # OverflowError for size larger than INT_MAX
  151. with open(support.TESTFN, "rb") as fp:
  152. data = os.read(fp.fileno(), size)
  153. # The test does not try to read more than 2 GB at once because the
  154. # operating system is free to return less bytes than requested.
  155. self.assertEqual(data, b'test')
  156. def test_write(self):
  157. # os.write() accepts bytes- and buffer-like objects but not strings
  158. fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY)
  159. self.assertRaises(TypeError, os.write, fd, "beans")
  160. os.write(fd, b"bacon\n")
  161. os.write(fd, bytearray(b"eggs\n"))
  162. os.write(fd, memoryview(b"spam\n"))
  163. os.close(fd)
  164. with open(support.TESTFN, "rb") as fobj:
  165. self.assertEqual(fobj.read().splitlines(),
  166. [b"bacon", b"eggs", b"spam"])
  167. def write_windows_console(self, *args):
  168. retcode = subprocess.call(args,
  169. # use a new console to not flood the test output
  170. creationflags=subprocess.CREATE_NEW_CONSOLE,
  171. # use a shell to hide the console window (SW_HIDE)
  172. shell=True)
  173. self.assertEqual(retcode, 0)
  174. @unittest.skipUnless(sys.platform == 'win32',
  175. 'test specific to the Windows console')
  176. def test_write_windows_console(self):
  177. # Issue #11395: the Windows console returns an error (12: not enough
  178. # space error) on writing into stdout if stdout mode is binary and the
  179. # length is greater than 66,000 bytes (or less, depending on heap
  180. # usage).
  181. code = "print('x' * 100000)"
  182. self.write_windows_console(sys.executable, "-c", code)
  183. self.write_windows_console(sys.executable, "-u", "-c", code)
  184. def fdopen_helper(self, *args):
  185. fd = os.open(support.TESTFN, os.O_RDONLY)
  186. f = os.fdopen(fd, *args)
  187. f.close()
  188. def test_fdopen(self):
  189. fd = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
  190. os.close(fd)
  191. self.fdopen_helper()
  192. self.fdopen_helper('r')
  193. self.fdopen_helper('r', 100)
  194. def test_replace(self):
  195. TESTFN2 = support.TESTFN + ".2"
  196. self.addCleanup(support.unlink, support.TESTFN)
  197. self.addCleanup(support.unlink, TESTFN2)
  198. create_file(support.TESTFN, b"1")
  199. create_file(TESTFN2, b"2")
  200. os.replace(support.TESTFN, TESTFN2)
  201. self.assertRaises(FileNotFoundError, os.stat, support.TESTFN)
  202. with open(TESTFN2, 'r') as f:
  203. self.assertEqual(f.read(), "1")
  204. def test_open_keywords(self):
  205. f = os.open(path=__file__, flags=os.O_RDONLY, mode=0o777,
  206. dir_fd=None)
  207. os.close(f)
  208. def test_symlink_keywords(self):
  209. symlink = support.get_attribute(os, "symlink")
  210. try:
  211. symlink(src='target', dst=support.TESTFN,
  212. target_is_directory=False, dir_fd=None)
  213. except (NotImplementedError, OSError):
  214. pass # No OS support or unprivileged user
  215. # Test attributes on return values from os.*stat* family.
  216. class StatAttributeTests(unittest.TestCase):
  217. def setUp(self):
  218. self.fname = support.TESTFN
  219. self.addCleanup(support.unlink, self.fname)
  220. create_file(self.fname, b"ABC")
  221. @unittest.skipUnless(hasattr(os, 'stat'), 'test needs os.stat()')
  222. def check_stat_attributes(self, fname):
  223. result = os.stat(fname)
  224. # Make sure direct access works
  225. self.assertEqual(result[stat.ST_SIZE], 3)
  226. self.assertEqual(result.st_size, 3)
  227. # Make sure all the attributes are there
  228. members = dir(result)
  229. for name in dir(stat):
  230. if name[:3] == 'ST_':
  231. attr = name.lower()
  232. if name.endswith("TIME"):
  233. def trunc(x): return int(x)
  234. else:
  235. def trunc(x): return x
  236. self.assertEqual(trunc(getattr(result, attr)),
  237. result[getattr(stat, name)])
  238. self.assertIn(attr, members)
  239. # Make sure that the st_?time and st_?time_ns fields roughly agree
  240. # (they should always agree up to around tens-of-microseconds)
  241. for name in 'st_atime st_mtime st_ctime'.split():
  242. floaty = int(getattr(result, name) * 100000)
  243. nanosecondy = getattr(result, name + "_ns") // 10000
  244. self.assertAlmostEqual(floaty, nanosecondy, delta=2)
  245. try:
  246. result[200]
  247. self.fail("No exception raised")
  248. except IndexError:
  249. pass
  250. # Make sure that assignment fails
  251. try:
  252. result.st_mode = 1
  253. self.fail("No exception raised")
  254. except AttributeError:
  255. pass
  256. try:
  257. result.st_rdev = 1
  258. self.fail("No exception raised")
  259. except (AttributeError, TypeError):
  260. pass
  261. try:
  262. result.parrot = 1
  263. self.fail("No exception raised")
  264. except AttributeError:
  265. pass
  266. # Use the stat_result constructor with a too-short tuple.
  267. try:
  268. result2 = os.stat_result((10,))
  269. self.fail("No exception raised")
  270. except TypeError:
  271. pass
  272. # Use the constructor with a too-long tuple.
  273. try:
  274. result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
  275. except TypeError:
  276. pass
  277. def test_stat_attributes(self):
  278. self.check_stat_attributes(self.fname)
  279. def test_stat_attributes_bytes(self):
  280. try:
  281. fname = self.fname.encode(sys.getfilesystemencoding())
  282. except UnicodeEncodeError:
  283. self.skipTest("cannot encode %a for the filesystem" % self.fname)
  284. with bytes_filename_warn(True):
  285. self.check_stat_attributes(fname)
  286. def test_stat_result_pickle(self):
  287. result = os.stat(self.fname)
  288. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  289. p = pickle.dumps(result, proto)
  290. self.assertIn(b'stat_result', p)
  291. if proto < 4:
  292. self.assertIn(b'cos\nstat_result\n', p)
  293. unpickled = pickle.loads(p)
  294. self.assertEqual(result, unpickled)
  295. @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
  296. def test_statvfs_attributes(self):
  297. try:
  298. result = os.statvfs(self.fname)
  299. except OSError as e:
  300. # On AtheOS, glibc always returns ENOSYS
  301. if e.errno == errno.ENOSYS:
  302. self.skipTest('os.statvfs() failed with ENOSYS')
  303. # Make sure direct access works
  304. self.assertEqual(result.f_bfree, result[3])
  305. # Make sure all the attributes are there.
  306. members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files',
  307. 'ffree', 'favail', 'flag', 'namemax')
  308. for value, member in enumerate(members):
  309. self.assertEqual(getattr(result, 'f_' + member), result[value])
  310. # Make sure that assignment really fails
  311. try:
  312. result.f_bfree = 1
  313. self.fail("No exception raised")
  314. except AttributeError:
  315. pass
  316. try:
  317. result.parrot = 1
  318. self.fail("No exception raised")
  319. except AttributeError:
  320. pass
  321. # Use the constructor with a too-short tuple.
  322. try:
  323. result2 = os.statvfs_result((10,))
  324. self.fail("No exception raised")
  325. except TypeError:
  326. pass
  327. # Use the constructor with a too-long tuple.
  328. try:
  329. result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
  330. except TypeError:
  331. pass
  332. @unittest.skipUnless(hasattr(os, 'statvfs'),
  333. "need os.statvfs()")
  334. def test_statvfs_result_pickle(self):
  335. try:
  336. result = os.statvfs(self.fname)
  337. except OSError as e:
  338. # On AtheOS, glibc always returns ENOSYS
  339. if e.errno == errno.ENOSYS:
  340. self.skipTest('os.statvfs() failed with ENOSYS')
  341. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  342. p = pickle.dumps(result, proto)
  343. self.assertIn(b'statvfs_result', p)
  344. if proto < 4:
  345. self.assertIn(b'cos\nstatvfs_result\n', p)
  346. unpickled = pickle.loads(p)
  347. self.assertEqual(result, unpickled)
  348. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  349. def test_1686475(self):
  350. # Verify that an open file can be stat'ed
  351. try:
  352. os.stat(r"c:\pagefile.sys")
  353. except FileNotFoundError:
  354. self.skipTest(r'c:\pagefile.sys does not exist')
  355. except OSError as e:
  356. self.fail("Could not stat pagefile.sys")
  357. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  358. @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
  359. def test_15261(self):
  360. # Verify that stat'ing a closed fd does not cause crash
  361. r, w = os.pipe()
  362. try:
  363. os.stat(r) # should not raise error
  364. finally:
  365. os.close(r)
  366. os.close(w)
  367. with self.assertRaises(OSError) as ctx:
  368. os.stat(r)
  369. self.assertEqual(ctx.exception.errno, errno.EBADF)
  370. def check_file_attributes(self, result):
  371. self.assertTrue(hasattr(result, 'st_file_attributes'))
  372. self.assertTrue(isinstance(result.st_file_attributes, int))
  373. self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF)
  374. @unittest.skipUnless(sys.platform == "win32",
  375. "st_file_attributes is Win32 specific")
  376. def test_file_attributes(self):
  377. # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set)
  378. result = os.stat(self.fname)
  379. self.check_file_attributes(result)
  380. self.assertEqual(
  381. result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
  382. 0)
  383. # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set)
  384. dirname = support.TESTFN + "dir"
  385. os.mkdir(dirname)
  386. self.addCleanup(os.rmdir, dirname)
  387. result = os.stat(dirname)
  388. self.check_file_attributes(result)
  389. self.assertEqual(
  390. result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
  391. stat.FILE_ATTRIBUTE_DIRECTORY)
  392. class UtimeTests(unittest.TestCase):
  393. def setUp(self):
  394. self.dirname = support.TESTFN
  395. self.fname = os.path.join(self.dirname, "f1")
  396. self.addCleanup(support.rmtree, self.dirname)
  397. os.mkdir(self.dirname)
  398. create_file(self.fname)
  399. def restore_float_times(state):
  400. with ignore_deprecation_warnings('stat_float_times'):
  401. os.stat_float_times(state)
  402. # ensure that st_atime and st_mtime are float
  403. with ignore_deprecation_warnings('stat_float_times'):
  404. old_float_times = os.stat_float_times(-1)
  405. self.addCleanup(restore_float_times, old_float_times)
  406. os.stat_float_times(True)
  407. def support_subsecond(self, filename):
  408. # Heuristic to check if the filesystem supports timestamp with
  409. # subsecond resolution: check if float and int timestamps are different
  410. st = os.stat(filename)
  411. return ((st.st_atime != st[7])
  412. or (st.st_mtime != st[8])
  413. or (st.st_ctime != st[9]))
  414. def _test_utime(self, set_time, filename=None):
  415. if not filename:
  416. filename = self.fname
  417. support_subsecond = self.support_subsecond(filename)
  418. if support_subsecond:
  419. # Timestamp with a resolution of 1 microsecond (10^-6).
  420. #
  421. # The resolution of the C internal function used by os.utime()
  422. # depends on the platform: 1 sec, 1 us, 1 ns. Writing a portable
  423. # test with a resolution of 1 ns requires more work:
  424. # see the issue #15745.
  425. atime_ns = 1002003000 # 1.002003 seconds
  426. mtime_ns = 4005006000 # 4.005006 seconds
  427. else:
  428. # use a resolution of 1 second
  429. atime_ns = 5 * 10**9
  430. mtime_ns = 8 * 10**9
  431. set_time(filename, (atime_ns, mtime_ns))
  432. st = os.stat(filename)
  433. if support_subsecond:
  434. self.assertAlmostEqual(st.st_atime, atime_ns * 1e-9, delta=1e-6)
  435. self.assertAlmostEqual(st.st_mtime, mtime_ns * 1e-9, delta=1e-6)
  436. else:
  437. self.assertEqual(st.st_atime, atime_ns * 1e-9)
  438. self.assertEqual(st.st_mtime, mtime_ns * 1e-9)
  439. self.assertEqual(st.st_atime_ns, atime_ns)
  440. self.assertEqual(st.st_mtime_ns, mtime_ns)
  441. def test_utime(self):
  442. def set_time(filename, ns):
  443. # test the ns keyword parameter
  444. os.utime(filename, ns=ns)
  445. self._test_utime(set_time)
  446. @staticmethod
  447. def ns_to_sec(ns):
  448. # Convert a number of nanosecond (int) to a number of seconds (float).
  449. # Round towards infinity by adding 0.5 nanosecond to avoid rounding
  450. # issue, os.utime() rounds towards minus infinity.
  451. return (ns * 1e-9) + 0.5e-9
  452. def test_utime_by_indexed(self):
  453. # pass times as floating point seconds as the second indexed parameter
  454. def set_time(filename, ns):
  455. atime_ns, mtime_ns = ns
  456. atime = self.ns_to_sec(atime_ns)
  457. mtime = self.ns_to_sec(mtime_ns)
  458. # test utimensat(timespec), utimes(timeval), utime(utimbuf)
  459. # or utime(time_t)
  460. os.utime(filename, (atime, mtime))
  461. self._test_utime(set_time)
  462. def test_utime_by_times(self):
  463. def set_time(filename, ns):
  464. atime_ns, mtime_ns = ns
  465. atime = self.ns_to_sec(atime_ns)
  466. mtime = self.ns_to_sec(mtime_ns)
  467. # test the times keyword parameter
  468. os.utime(filename, times=(atime, mtime))
  469. self._test_utime(set_time)
  470. @unittest.skipUnless(os.utime in os.supports_follow_symlinks,
  471. "follow_symlinks support for utime required "
  472. "for this test.")
  473. def test_utime_nofollow_symlinks(self):
  474. def set_time(filename, ns):
  475. # use follow_symlinks=False to test utimensat(timespec)
  476. # or lutimes(timeval)
  477. os.utime(filename, ns=ns, follow_symlinks=False)
  478. self._test_utime(set_time)
  479. @unittest.skipUnless(os.utime in os.supports_fd,
  480. "fd support for utime required for this test.")
  481. def test_utime_fd(self):
  482. def set_time(filename, ns):
  483. with open(filename, 'wb', 0) as fp:
  484. # use a file descriptor to test futimens(timespec)
  485. # or futimes(timeval)
  486. os.utime(fp.fileno(), ns=ns)
  487. self._test_utime(set_time)
  488. @unittest.skipUnless(os.utime in os.supports_dir_fd,
  489. "dir_fd support for utime required for this test.")
  490. def test_utime_dir_fd(self):
  491. def set_time(filename, ns):
  492. dirname, name = os.path.split(filename)
  493. dirfd = os.open(dirname, os.O_RDONLY)
  494. try:
  495. # pass dir_fd to test utimensat(timespec) or futimesat(timeval)
  496. os.utime(name, dir_fd=dirfd, ns=ns)
  497. finally:
  498. os.close(dirfd)
  499. self._test_utime(set_time)
  500. def test_utime_directory(self):
  501. def set_time(filename, ns):
  502. # test calling os.utime() on a directory
  503. os.utime(filename, ns=ns)
  504. self._test_utime(set_time, filename=self.dirname)
  505. def _test_utime_current(self, set_time):
  506. # Get the system clock
  507. current = time.time()
  508. # Call os.utime() to set the timestamp to the current system clock
  509. set_time(self.fname)
  510. if not self.support_subsecond(self.fname):
  511. delta = 1.0
  512. else:
  513. # On Windows, the usual resolution of time.time() is 15.6 ms
  514. delta = 0.020
  515. st = os.stat(self.fname)
  516. msg = ("st_time=%r, current=%r, dt=%r"
  517. % (st.st_mtime, current, st.st_mtime - current))
  518. self.assertAlmostEqual(st.st_mtime, current,
  519. delta=delta, msg=msg)
  520. def test_utime_current(self):
  521. def set_time(filename):
  522. # Set to the current time in the new way
  523. os.utime(self.fname)
  524. self._test_utime_current(set_time)
  525. def test_utime_current_old(self):
  526. def set_time(filename):
  527. # Set to the current time in the old explicit way.
  528. os.utime(self.fname, None)
  529. self._test_utime_current(set_time)
  530. def get_file_system(self, path):
  531. if sys.platform == 'win32':
  532. root = os.path.splitdrive(os.path.abspath(path))[0] + '\\'
  533. import ctypes
  534. kernel32 = ctypes.windll.kernel32
  535. buf = ctypes.create_unicode_buffer("", 100)
  536. ok = kernel32.GetVolumeInformationW(root, None, 0,
  537. None, None, None,
  538. buf, len(buf))
  539. if ok:
  540. return buf.value
  541. # return None if the filesystem is unknown
  542. def test_large_time(self):
  543. # Many filesystems are limited to the year 2038. At least, the test
  544. # pass with NTFS filesystem.
  545. if self.get_file_system(self.dirname) != "NTFS":
  546. self.skipTest("requires NTFS")
  547. large = 5000000000 # some day in 2128
  548. os.utime(self.fname, (large, large))
  549. self.assertEqual(os.stat(self.fname).st_mtime, large)
  550. def test_utime_invalid_arguments(self):
  551. # seconds and nanoseconds parameters are mutually exclusive
  552. with self.assertRaises(ValueError):
  553. os.utime(self.fname, (5, 5), ns=(5, 5))
  554. from test import mapping_tests
  555. class EnvironTests(mapping_tests.BasicTestMappingProtocol):
  556. """check that os.environ object conform to mapping protocol"""
  557. type2test = None
  558. def setUp(self):
  559. self.__save = dict(os.environ)
  560. if os.supports_bytes_environ:
  561. self.__saveb = dict(os.environb)
  562. for key, value in self._reference().items():
  563. os.environ[key] = value
  564. def tearDown(self):
  565. os.environ.clear()
  566. os.environ.update(self.__save)
  567. if os.supports_bytes_environ:
  568. os.environb.clear()
  569. os.environb.update(self.__saveb)
  570. def _reference(self):
  571. return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
  572. def _empty_mapping(self):
  573. os.environ.clear()
  574. return os.environ
  575. # Bug 1110478
  576. @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
  577. 'requires a shell')
  578. def test_update2(self):
  579. os.environ.clear()
  580. os.environ.update(HELLO="World")
  581. with os.popen("%s -c 'echo $HELLO'" % unix_shell) as popen:
  582. value = popen.read().strip()
  583. self.assertEqual(value, "World")
  584. @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
  585. 'requires a shell')
  586. def test_os_popen_iter(self):
  587. with os.popen("%s -c 'echo \"line1\nline2\nline3\"'"
  588. % unix_shell) as popen:
  589. it = iter(popen)
  590. self.assertEqual(next(it), "line1\n")
  591. self.assertEqual(next(it), "line2\n")
  592. self.assertEqual(next(it), "line3\n")
  593. self.assertRaises(StopIteration, next, it)
  594. # Verify environ keys and values from the OS are of the
  595. # correct str type.
  596. def test_keyvalue_types(self):
  597. for key, val in os.environ.items():
  598. self.assertEqual(type(key), str)
  599. self.assertEqual(type(val), str)
  600. def test_items(self):
  601. for key, value in self._reference().items():
  602. self.assertEqual(os.environ.get(key), value)
  603. # Issue 7310
  604. def test___repr__(self):
  605. """Check that the repr() of os.environ looks like environ({...})."""
  606. env = os.environ
  607. self.assertEqual(repr(env), 'environ({{{}}})'.format(', '.join(
  608. '{!r}: {!r}'.format(key, value)
  609. for key, value in env.items())))
  610. def test_get_exec_path(self):
  611. defpath_list = os.defpath.split(os.pathsep)
  612. test_path = ['/monty', '/python', '', '/flying/circus']
  613. test_env = {'PATH': os.pathsep.join(test_path)}
  614. saved_environ = os.environ
  615. try:
  616. os.environ = dict(test_env)
  617. # Test that defaulting to os.environ works.
  618. self.assertSequenceEqual(test_path, os.get_exec_path())
  619. self.assertSequenceEqual(test_path, os.get_exec_path(env=None))
  620. finally:
  621. os.environ = saved_environ
  622. # No PATH environment variable
  623. self.assertSequenceEqual(defpath_list, os.get_exec_path({}))
  624. # Empty PATH environment variable
  625. self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''}))
  626. # Supplied PATH environment variable
  627. self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
  628. if os.supports_bytes_environ:
  629. # env cannot contain 'PATH' and b'PATH' keys
  630. try:
  631. # ignore BytesWarning warning
  632. with warnings.catch_warnings(record=True):
  633. mixed_env = {'PATH': '1', b'PATH': b'2'}
  634. except BytesWarning:
  635. # mixed_env cannot be created with python -bb
  636. pass
  637. else:
  638. self.assertRaises(ValueError, os.get_exec_path, mixed_env)
  639. # bytes key and/or value
  640. self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
  641. ['abc'])
  642. self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
  643. ['abc'])
  644. self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
  645. ['abc'])
  646. @unittest.skipUnless(os.supports_bytes_environ,
  647. "os.environb required for this test.")
  648. def test_environb(self):
  649. # os.environ -> os.environb
  650. value = 'euro\u20ac'
  651. try:
  652. value_bytes = value.encode(sys.getfilesystemencoding(),
  653. 'surrogateescape')
  654. except UnicodeEncodeError:
  655. msg = "U+20AC character is not encodable to %s" % (
  656. sys.getfilesystemencoding(),)
  657. self.skipTest(msg)
  658. os.environ['unicode'] = value
  659. self.assertEqual(os.environ['unicode'], value)
  660. self.assertEqual(os.environb[b'unicode'], value_bytes)
  661. # os.environb -> os.environ
  662. value = b'\xff'
  663. os.environb[b'bytes'] = value
  664. self.assertEqual(os.environb[b'bytes'], value)
  665. value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
  666. self.assertEqual(os.environ['bytes'], value_str)
  667. # On FreeBSD < 7 and OS X < 10.6, unsetenv() doesn't return a value (issue
  668. # #13415).
  669. @support.requires_freebsd_version(7)
  670. @support.requires_mac_ver(10, 6)
  671. def test_unset_error(self):
  672. if sys.platform == "win32":
  673. # an environment variable is limited to 32,767 characters
  674. key = 'x' * 50000
  675. self.assertRaises(ValueError, os.environ.__delitem__, key)
  676. else:
  677. # "=" is not allowed in a variable name
  678. key = 'key='
  679. self.assertRaises(OSError, os.environ.__delitem__, key)
  680. def test_key_type(self):
  681. missing = 'missingkey'
  682. self.assertNotIn(missing, os.environ)
  683. with self.assertRaises(KeyError) as cm:
  684. os.environ[missing]
  685. self.assertIs(cm.exception.args[0], missing)
  686. self.assertTrue(cm.exception.__suppress_context__)
  687. with self.assertRaises(KeyError) as cm:
  688. del os.environ[missing]
  689. self.assertIs(cm.exception.args[0], missing)
  690. self.assertTrue(cm.exception.__suppress_context__)
  691. class WalkTests(unittest.TestCase):
  692. """Tests for os.walk()."""
  693. # Wrapper to hide minor differences between os.walk and os.fwalk
  694. # to tests both functions with the same code base
  695. def walk(self, top, **kwargs):
  696. if 'follow_symlinks' in kwargs:
  697. kwargs['followlinks'] = kwargs.pop('follow_symlinks')
  698. return os.walk(top, **kwargs)
  699. def setUp(self):
  700. join = os.path.join
  701. self.addCleanup(support.rmtree, support.TESTFN)
  702. # Build:
  703. # TESTFN/
  704. # TEST1/ a file kid and two directory kids
  705. # tmp1
  706. # SUB1/ a file kid and a directory kid
  707. # tmp2
  708. # SUB11/ no kids
  709. # SUB2/ a file kid and a dirsymlink kid
  710. # tmp3
  711. # link/ a symlink to TESTFN.2
  712. # broken_link
  713. # TEST2/
  714. # tmp4 a lone file
  715. self.walk_path = join(support.TESTFN, "TEST1")
  716. self.sub1_path = join(self.walk_path, "SUB1")
  717. self.sub11_path = join(self.sub1_path, "SUB11")
  718. sub2_path = join(self.walk_path, "SUB2")
  719. tmp1_path = join(self.walk_path, "tmp1")
  720. tmp2_path = join(self.sub1_path, "tmp2")
  721. tmp3_path = join(sub2_path, "tmp3")
  722. self.link_path = join(sub2_path, "link")
  723. t2_path = join(support.TESTFN, "TEST2")
  724. tmp4_path = join(support.TESTFN, "TEST2", "tmp4")
  725. broken_link_path = join(sub2_path, "broken_link")
  726. # Create stuff.
  727. os.makedirs(self.sub11_path)
  728. os.makedirs(sub2_path)
  729. os.makedirs(t2_path)
  730. for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
  731. with open(path, "x") as f:
  732. f.write("I'm " + path + " and proud of it. Blame test_os.\n")
  733. if support.can_symlink():
  734. os.symlink(os.path.abspath(t2_path), self.link_path)
  735. os.symlink('broken', broken_link_path, True)
  736. self.sub2_tree = (sub2_path, ["link"], ["broken_link", "tmp3"])
  737. else:
  738. self.sub2_tree = (sub2_path, [], ["tmp3"])
  739. def test_walk_topdown(self):
  740. # Walk top-down.
  741. all = list(self.walk(self.walk_path))
  742. self.assertEqual(len(all), 4)
  743. # We can't know which order SUB1 and SUB2 will appear in.
  744. # Not flipped: TESTFN, SUB1, SUB11, SUB2
  745. # flipped: TESTFN, SUB2, SUB1, SUB11
  746. flipped = all[0][1][0] != "SUB1"
  747. all[0][1].sort()
  748. all[3 - 2 * flipped][-1].sort()
  749. self.assertEqual(all[0], (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
  750. self.assertEqual(all[1 + flipped], (self.sub1_path, ["SUB11"], ["tmp2"]))
  751. self.assertEqual(all[2 + flipped], (self.sub11_path, [], []))
  752. self.assertEqual(all[3 - 2 * flipped], self.sub2_tree)
  753. def test_walk_prune(self):
  754. # Prune the search.
  755. all = []
  756. for root, dirs, files in self.walk(self.walk_path):
  757. all.append((root, dirs, files))
  758. # Don't descend into SUB1.
  759. if 'SUB1' in dirs:
  760. # Note that this also mutates the dirs we appended to all!
  761. dirs.remove('SUB1')
  762. self.assertEqual(len(all), 2)
  763. self.assertEqual(all[0],
  764. (self.walk_path, ["SUB2"], ["tmp1"]))
  765. all[1][-1].sort()
  766. self.assertEqual(all[1], self.sub2_tree)
  767. def test_walk_bottom_up(self):
  768. # Walk bottom-up.
  769. all = list(self.walk(self.walk_path, topdown=False))
  770. self.assertEqual(len(all), 4, all)
  771. # We can't know which order SUB1 and SUB2 will appear in.
  772. # Not flipped: SUB11, SUB1, SUB2, TESTFN
  773. # flipped: SUB2, SUB11, SUB1, TESTFN
  774. flipped = all[3][1][0] != "SUB1"
  775. all[3][1].sort()
  776. all[2 - 2 * flipped][-1].sort()
  777. self.assertEqual(all[3],
  778. (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
  779. self.assertEqual(all[flipped],
  780. (self.sub11_path, [], []))
  781. self.assertEqual(all[flipped + 1],
  782. (self.sub1_path, ["SUB11"], ["tmp2"]))
  783. self.assertEqual(all[2 - 2 * flipped],
  784. self.sub2_tree)
  785. def test_walk_symlink(self):
  786. if not support.can_symlink():
  787. self.skipTest("need symlink support")
  788. # Walk, following symlinks.
  789. walk_it = self.walk(self.walk_path, follow_symlinks=True)
  790. for root, dirs, files in walk_it:
  791. if root == self.link_path:
  792. self.assertEqual(dirs, [])
  793. self.assertEqual(files, ["tmp4"])
  794. break
  795. else:
  796. self.fail("Didn't follow symlink with followlinks=True")
  797. def test_walk_bad_dir(self):
  798. # Walk top-down.
  799. errors = []
  800. walk_it = self.walk(self.walk_path, onerror=errors.append)
  801. root, dirs, files = next(walk_it)
  802. self.assertFalse(errors)
  803. dir1 = dirs[0]
  804. dir1new = dir1 + '.new'
  805. os.rename(os.path.join(root, dir1), os.path.join(root, dir1new))
  806. roots = [r for r, d, f in walk_it]
  807. self.assertTrue(errors)
  808. self.assertNotIn(os.path.join(root, dir1), roots)
  809. self.assertNotIn(os.path.join(root, dir1new), roots)
  810. for dir2 in dirs[1:]:
  811. self.assertIn(os.path.join(root, dir2), roots)
  812. @unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
  813. class FwalkTests(WalkTests):
  814. """Tests for os.fwalk()."""
  815. def walk(self, top, **kwargs):
  816. for root, dirs, files, root_fd in os.fwalk(top, **kwargs):
  817. yield (root, dirs, files)
  818. def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
  819. """
  820. compare with walk() results.
  821. """
  822. walk_kwargs = walk_kwargs.copy()
  823. fwalk_kwargs = fwalk_kwargs.copy()
  824. for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
  825. walk_kwargs.update(topdown=topdown, followlinks=follow_symlinks)
  826. fwalk_kwargs.update(topdown=topdown, follow_symlinks=follow_symlinks)
  827. expected = {}
  828. for root, dirs, files in os.walk(**walk_kwargs):
  829. expected[root] = (set(dirs), set(files))
  830. for root, dirs, files, rootfd in os.fwalk(**fwalk_kwargs):
  831. self.assertIn(root, expected)
  832. self.assertEqual(expected[root], (set(dirs), set(files)))
  833. def test_compare_to_walk(self):
  834. kwargs = {'top': support.TESTFN}
  835. self._compare_to_walk(kwargs, kwargs)
  836. def test_dir_fd(self):
  837. try:
  838. fd = os.open(".", os.O_RDONLY)
  839. walk_kwargs = {'top': support.TESTFN}
  840. fwalk_kwargs = walk_kwargs.copy()
  841. fwalk_kwargs['dir_fd'] = fd
  842. self._compare_to_walk(walk_kwargs, fwalk_kwargs)
  843. finally:
  844. os.close(fd)
  845. def test_yields_correct_dir_fd(self):
  846. # check returned file descriptors
  847. for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
  848. args = support.TESTFN, topdown, None
  849. for root, dirs, files, rootfd in os.fwalk(*args, follow_symlinks=follow_symlinks):
  850. # check that the FD is valid
  851. os.fstat(rootfd)
  852. # redundant check
  853. os.stat(rootfd)
  854. # check that listdir() returns consistent information
  855. self.assertEqual(set(os.listdir(rootfd)), set(dirs) | set(files))
  856. def test_fd_leak(self):
  857. # Since we're opening a lot of FDs, we must be careful to avoid leaks:
  858. # we both check that calling fwalk() a large number of times doesn't
  859. # yield EMFILE, and that the minimum allocated FD hasn't changed.
  860. minfd = os.dup(1)
  861. os.close(minfd)
  862. for i in range(256):
  863. for x in os.fwalk(support.TESTFN):
  864. pass
  865. newfd = os.dup(1)
  866. self.addCleanup(os.close, newfd)
  867. self.assertEqual(newfd, minfd)
  868. class BytesWalkTests(WalkTests):
  869. """Tests for os.walk() with bytes."""
  870. def setUp(self):
  871. super().setUp()
  872. self.stack = contextlib.ExitStack()
  873. if os.name == 'nt':
  874. self.stack.enter_context(bytes_filename_warn(False))
  875. def tearDown(self):
  876. self.stack.close()
  877. super().tearDown()
  878. def walk(self, top, **kwargs):
  879. if 'follow_symlinks' in kwargs:
  880. kwargs['followlinks'] = kwargs.pop('follow_symlinks')
  881. for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs):
  882. root = os.fsdecode(broot)
  883. dirs = list(map(os.fsdecode, bdirs))
  884. files = list(map(os.fsdecode, bfiles))
  885. yield (root, dirs, files)
  886. bdirs[:] = list(map(os.fsencode, dirs))
  887. bfiles[:] = list(map(os.fsencode, files))
  888. class MakedirTests(unittest.TestCase):
  889. def setUp(self):
  890. os.mkdir(support.TESTFN)
  891. def test_makedir(self):
  892. base = support.TESTFN
  893. path = os.path.join(base, 'dir1', 'dir2', 'dir3')
  894. os.makedirs(path) # Should work
  895. path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4')
  896. os.makedirs(path)
  897. # Try paths with a '.' in them
  898. self.assertRaises(OSError, os.makedirs, os.curdir)
  899. path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir)
  900. os.makedirs(path)
  901. path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4',
  902. 'dir5', 'dir6')
  903. os.makedirs(path)
  904. def test_exist_ok_existing_directory(self):
  905. path = os.path.join(support.TESTFN, 'dir1')
  906. mode = 0o777
  907. old_mask = os.umask(0o022)
  908. os.makedirs(path, mode)
  909. self.assertRaises(OSError, os.makedirs, path, mode)
  910. self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
  911. os.makedirs(path, 0o776, exist_ok=True)
  912. os.makedirs(path, mode=mode, exist_ok=True)
  913. os.umask(old_mask)
  914. # Issue #25583: A drive root could raise PermissionError on Windows
  915. os.makedirs(os.path.abspath('/'), exist_ok=True)
  916. def test_exist_ok_s_isgid_directory(self):
  917. path = os.path.join(support.TESTFN, 'dir1')
  918. S_ISGID = stat.S_ISGID
  919. mode = 0o777
  920. old_mask = os.umask(0o022)
  921. try:
  922. existing_testfn_mode = stat.S_IMODE(
  923. os.lstat(support.TESTFN).st_mode)
  924. try:
  925. os.chmod(support.TESTFN, existing_testfn_mode | S_ISGID)
  926. except PermissionError:
  927. raise unittest.SkipTest('Cannot set S_ISGID for dir.')
  928. if (os.lstat(support.TESTFN).st_mode & S_ISGID != S_ISGID):
  929. raise unittest.SkipTest('No support for S_ISGID dir mode.')
  930. # The os should apply S_ISGID from the parent dir for us, but
  931. # this test need not depend on that behavior. Be explicit.
  932. os.makedirs(path, mode | S_ISGID)
  933. # http://bugs.python.org/issue14992
  934. # Should not fail when the bit is already set.
  935. os.makedirs(path, mode, exist_ok=True)
  936. # remove the bit.
  937. os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
  938. # May work even when the bit is not already set when demanded.
  939. os.makedirs(path, mode | S_ISGID, exist_ok=True)
  940. finally:
  941. os.umask(old_mask)
  942. def test_exist_ok_existing_regular_file(self):
  943. base = support.TESTFN
  944. path = os.path.join(support.TESTFN, 'dir1')
  945. f = open(path, 'w')
  946. f.write('abc')
  947. f.close()
  948. self.assertRaises(OSError, os.makedirs, path)
  949. self.assertRaises(OSError, os.makedirs, path, exist_ok=False)
  950. self.assertRaises(OSError, os.makedirs, path, exist_ok=True)
  951. os.remove(path)
  952. def tearDown(self):
  953. path = os.path.join(support.TESTFN, 'dir1', 'dir2', 'dir3',
  954. 'dir4', 'dir5', 'dir6')
  955. # If the tests failed, the bottom-most directory ('../dir6')
  956. # may not have been created, so we look for the outermost directory
  957. # that exists.
  958. while not os.path.exists(path) and path != support.TESTFN:
  959. path = os.path.dirname(path)
  960. os.removedirs(path)
  961. @unittest.skipUnless(hasattr(os, 'chown'), "Test needs chown")
  962. class ChownFileTests(unittest.TestCase):
  963. @classmethod
  964. def setUpClass(cls):
  965. os.mkdir(support.TESTFN)
  966. def test_chown_uid_gid_arguments_must_be_index(self):
  967. stat = os.stat(support.TESTFN)
  968. uid = stat.st_uid
  969. gid = stat.st_gid
  970. for value in (-1.0, -1j, decimal.Decimal(-1), fractions.Fraction(-2, 2)):
  971. self.assertRaises(TypeError, os.chown, support.TESTFN, value, gid)
  972. self.assertRaises(TypeError, os.chown, support.TESTFN, uid, value)
  973. self.assertIsNone(os.chown(support.TESTFN, uid, gid))
  974. self.assertIsNone(os.chown(support.TESTFN, -1, -1))
  975. @unittest.skipUnless(len(groups) > 1, "test needs more than one group")
  976. def test_chown(self):
  977. gid_1, gid_2 = groups[:2]
  978. uid = os.stat(support.TESTFN).st_uid
  979. os.chown(support.TESTFN, uid, gid_1)
  980. gid = os.stat(support.TESTFN).st_gid
  981. self.assertEqual(gid, gid_1)
  982. os.chown(support.TESTFN, uid, gid_2)
  983. gid = os.stat(support.TESTFN).st_gid
  984. self.assertEqual(gid, gid_2)
  985. @unittest.skipUnless(root_in_posix and len(all_users) > 1,
  986. "test needs root privilege and more than one user")
  987. def test_chown_with_root(self):
  988. uid_1, uid_2 = all_users[:2]
  989. gid = os.stat(support.TESTFN).st_gid
  990. os.chown(support.TESTFN, uid_1, gid)
  991. uid = os.stat(support.TESTFN).st_uid
  992. self.assertEqual(uid, uid_1)
  993. os.chown(support.TESTFN, uid_2, gid)
  994. uid = os.stat(support.TESTFN).st_uid
  995. self.assertEqual(uid, uid_2)
  996. @unittest.skipUnless(not root_in_posix and len(all_users) > 1,
  997. "test needs non-root account and more than one user")
  998. def test_chown_without_permission(self):
  999. uid_1, uid_2 = all_users[:2]
  1000. gid = os.stat(support.TESTFN).st_gid
  1001. with self.assertRaises(PermissionError):
  1002. os.chown(support.TESTFN, uid_1, gid)
  1003. os.chown(support.TESTFN, uid_2, gid)
  1004. @classmethod
  1005. def tearDownClass(cls):
  1006. os.rmdir(support.TESTFN)
  1007. class RemoveDirsTests(unittest.TestCase):
  1008. def setUp(self):
  1009. os.makedirs(support.TESTFN)
  1010. def tearDown(self):
  1011. support.rmtree(support.TESTFN)
  1012. def test_remove_all(self):
  1013. dira = os.path.join(support.TESTFN, 'dira')
  1014. os.mkdir(dira)
  1015. dirb = os.path.join(dira, 'dirb')
  1016. os.mkdir(dirb)
  1017. os.removedirs(dirb)
  1018. self.assertFalse(os.path.exists(dirb))
  1019. self.assertFalse(os.path.exists(dira))
  1020. self.assertFalse(os.path.exists(support.TESTFN))
  1021. def test_remove_partial(self):
  1022. dira = os.path.join(support.TESTFN, 'dira')
  1023. os.mkdir(dira)
  1024. dirb = os.path.join(dira, 'dirb')
  1025. os.mkdir(dirb)
  1026. create_file(os.path.join(dira, 'file.txt'))
  1027. os.removedirs(dirb)
  1028. self.assertFalse(os.path.exists(dirb))
  1029. self.assertTrue(os.path.exists(dira))
  1030. self.assertTrue(os.path.exists(support.TESTFN))
  1031. def test_remove_nothing(self):
  1032. dira = os.path.join(support.TESTFN, 'dira')
  1033. os.mkdir(dira)
  1034. dirb = os.path.join(dira, 'dirb')
  1035. os.mkdir(dirb)
  1036. create_file(os.path.join(dirb, 'file.txt'))
  1037. with self.assertRaises(OSError):
  1038. os.removedirs(dirb)
  1039. self.assertTrue(os.path.exists(dirb))
  1040. self.assertTrue(os.path.exists(dira))
  1041. self.assertTrue(os.path.exists(support.TESTFN))
  1042. class DevNullTests(unittest.TestCase):
  1043. def test_devnull(self):
  1044. with open(os.devnull, 'wb', 0) as f:
  1045. f.write(b'hello')
  1046. f.close()
  1047. with open(os.devnull, 'rb') as f:
  1048. self.assertEqual(f.read(), b'')
  1049. class URandomTests(unittest.TestCase):
  1050. def test_urandom_length(self):
  1051. self.assertEqual(len(os.urandom(0)), 0)
  1052. self.assertEqual(len(os.urandom(1)), 1)
  1053. self.assertEqual(len(os.urandom(10)), 10)
  1054. self.assertEqual(len(os.urandom(100)), 100)
  1055. self.assertEqual(len(os.urandom(1000)), 1000)
  1056. def test_urandom_value(self):
  1057. data1 = os.urandom(16)
  1058. data2 = os.urandom(16)
  1059. self.assertNotEqual(data1, data2)
  1060. def get_urandom_subprocess(self, count):
  1061. code = '\n'.join((
  1062. 'import os, sys',
  1063. 'data = os.urandom(%s)' % count,
  1064. 'sys.stdout.buffer.write(data)',
  1065. 'sys.stdout.buffer.flush()'))
  1066. out = assert_python_ok('-c', code)
  1067. stdout = out[1]
  1068. self.assertEqual(len(stdout), 16)
  1069. return stdout
  1070. def test_urandom_subprocess(self):
  1071. data1 = self.get_urandom_subprocess(16)
  1072. data2 = self.get_urandom_subprocess(16)
  1073. self.assertNotEqual(data1, data2)
  1074. # os.urandom() doesn't use a file descriptor when it is implemented with the
  1075. # getentropy() function, the getrandom() function or the getrandom() syscall
  1076. OS_URANDOM_DONT_USE_FD = (
  1077. sysconfig.get_config_var('HAVE_GETENTROPY') == 1
  1078. or sysconfig.get_config_var('HAVE_GETRANDOM') == 1
  1079. or sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1)
  1080. @unittest.skipIf(OS_URANDOM_DONT_USE_FD ,
  1081. "os.random() does not use a file descriptor")
  1082. class URandomFDTests(unittest.TestCase):
  1083. @unittest.skipUnless(resource, "test requires the resource module")
  1084. def test_urandom_failure(self):
  1085. # Check urandom() failing when it is not able to open /dev/random.
  1086. # We spawn a new process to make the test more robust (if getrlimit()
  1087. # failed to restore the file descriptor limit after this, the whole
  1088. # test suite would crash; this actually happened on the OS X Tiger
  1089. # buildbot).
  1090. code = """if 1:
  1091. import errno
  1092. import os
  1093. import resource
  1094. soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
  1095. resource.setrlimit(resource.RLIMIT_NOFILE, (1, hard_limit))
  1096. try:
  1097. os.urandom(16)
  1098. except OSError as e:
  1099. assert e.errno == errno.EMFILE, e.errno
  1100. else:
  1101. raise AssertionError("OSError not raised")
  1102. """
  1103. assert_python_ok('-c', code)
  1104. def test_urandom_fd_closed(self):
  1105. # Issue #21207: urandom() should reopen its fd to /dev/urandom if
  1106. # closed.
  1107. code = """if 1:
  1108. import os
  1109. import sys
  1110. import test.support
  1111. os.urandom(4)
  1112. with test.support.SuppressCrashReport():
  1113. os.closerange(3, 256)
  1114. sys.stdout.buffer.write(os.urandom(4))
  1115. """
  1116. rc, out, err = assert_python_ok('-Sc', code)
  1117. def test_urandom_fd_reopened(self):
  1118. # Issue #21207: urandom() should detect its fd to /dev/urandom
  1119. # changed to something else, and reopen it.
  1120. self.addCleanup(support.unlink, support.TESTFN)
  1121. create_file(support.TESTFN, b"x" * 256)
  1122. code = """if 1:
  1123. import os
  1124. import sys
  1125. import test.support
  1126. os.urandom(4)
  1127. with test.support.SuppressCrashReport():
  1128. for fd in range(3, 256):
  1129. try:
  1130. os.close(fd)
  1131. except OSError:
  1132. pass
  1133. else:
  1134. # Found the urandom fd (XXX hopefully)
  1135. break
  1136. os.closerange(3, 256)
  1137. with open({TESTFN!r}, 'rb') as f:
  1138. os.dup2(f.fileno(), fd)
  1139. sys.stdout.buffer.write(os.urandom(4))
  1140. sys.stdout.buffer.write(os.urandom(4))
  1141. """.format(TESTFN=support.TESTFN)
  1142. rc, out, err = assert_python_ok('-Sc', code)
  1143. self.assertEqual(len(out), 8)
  1144. self.assertNotEqual(out[0:4], out[4:8])
  1145. rc, out2, err2 = assert_python_ok('-Sc', code)
  1146. self.assertEqual(len(out2), 8)
  1147. self.assertNotEqual(out2, out)
  1148. @contextlib.contextmanager
  1149. def _execvpe_mockup(defpath=None):
  1150. """
  1151. Stubs out execv and execve functions when used as context manager.
  1152. Records exec calls. The mock execv and execve functions always raise an
  1153. exception as they would normally never return.
  1154. """
  1155. # A list of tuples containing (function name, first arg, args)
  1156. # of calls to execv or execve that have been made.
  1157. calls = []
  1158. def mock_execv(name, *args):
  1159. calls.append(('execv', name, args))
  1160. raise RuntimeError("execv called")
  1161. def mock_execve(name, *args):
  1162. calls.append(('execve', name, args))
  1163. raise OSError(errno.ENOTDIR, "execve called")
  1164. try:
  1165. orig_execv = os.execv
  1166. orig_execve = os.execve
  1167. orig_defpath = os.defpath
  1168. os.execv = mock_execv
  1169. os.execve = mock_execve
  1170. if defpath is not None:
  1171. os.defpath = defpath
  1172. yield calls
  1173. finally:
  1174. os.execv = orig_execv
  1175. os.execve = orig_execve
  1176. os.defpath = orig_defpath
  1177. class ExecTests(unittest.TestCase):
  1178. @unittest.skipIf(USING_LINUXTHREADS,
  1179. "avoid triggering a linuxthreads bug: see issue #4970")
  1180. def test_execvpe_with_bad_program(self):
  1181. self.assertRaises(OSError, os.execvpe, 'no such app-',
  1182. ['no such app-'], None)
  1183. def test_execvpe_with_bad_arglist(self):
  1184. self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
  1185. @unittest.skipUnless(hasattr(os, '_execvpe'),
  1186. "No internal os._execvpe function to test.")
  1187. def _test_internal_execvpe(self, test_type):
  1188. program_path = os.sep + 'absolutepath'
  1189. if test_type is bytes:
  1190. program = b'executable'
  1191. fullpath = os.path.join(os.fsencode(program_path), program)
  1192. native_fullpath = fullpath
  1193. arguments = [b'progname', 'arg1', 'arg2']
  1194. else:
  1195. program = 'executable'
  1196. arguments = ['progname', 'arg1', 'arg2']
  1197. fullpath = os.path.join(program_path, program)
  1198. if os.name != "nt":
  1199. native_fullpath = os.fsencode(fullpath)
  1200. else:
  1201. native_fullpath = fullpath
  1202. env = {'spam': 'beans'}
  1203. # test os._execvpe() with an absolute path
  1204. with _execvpe_mockup() as calls:
  1205. self.assertRaises(RuntimeError,
  1206. os._execvpe, fullpath, arguments)
  1207. self.assertEqual(len(calls), 1)
  1208. self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
  1209. # test os._execvpe() with a relative path:
  1210. # os.get_exec_path() returns defpath
  1211. with _execvpe_mockup(defpath=program_path) as calls:
  1212. self.assertRaises(OSError,
  1213. os._execvpe, program, arguments, env=env)
  1214. self.assertEqual(len(calls), 1)
  1215. self.assertSequenceEqual(calls[0],
  1216. ('execve', native_fullpath, (arguments, env)))
  1217. # test os._execvpe() with a relative path:
  1218. # os.get_exec_path() reads the 'PATH' variable
  1219. with _execvpe_mockup() as calls:
  1220. env_path = env.copy()
  1221. if test_type is bytes:
  1222. env_path[b'PATH'] = program_path
  1223. else:
  1224. env_path['PATH'] = program_path
  1225. self.assertRaises(OSError,
  1226. os._execvpe, program, arguments, env=env_path)
  1227. self.assertEqual(len(calls), 1)
  1228. self.assertSequenceEqual(calls[0],
  1229. ('execve', native_fullpath, (arguments, env_path)))
  1230. def test_internal_execvpe_str(self):
  1231. self._test_internal_execvpe(str)
  1232. if os.name != "nt":
  1233. self._test_internal_execvpe(bytes)
  1234. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  1235. class Win32ErrorTests(unittest.TestCase):
  1236. def setUp(self):
  1237. try:
  1238. os.stat(support.TESTFN)
  1239. except FileNotFoundError:
  1240. exists = False
  1241. except OSError as exc:
  1242. exists = True
  1243. self.fail("file %s must not exist; os.stat failed with %s"
  1244. % (support.TESTFN, exc))
  1245. else:
  1246. self.fail("file %s must not exist" % support.TESTFN)
  1247. def test_rename(self):
  1248. self.assertRaises(OSError, os.rename, support.TESTFN, support.TESTFN+".bak")
  1249. def test_remove(self):
  1250. self.assertRaises(OSError, os.remove, support.TESTFN)
  1251. def test_chdir(self):
  1252. self.assertRaises(OSError, os.chdir, support.TESTFN)
  1253. def test_mkdir(self):
  1254. self.addCleanup(support.unlink, support.TESTFN)
  1255. with open(support.TESTFN, "x") as f:
  1256. self.assertRaises(OSError, os.mkdir, support.TESTFN)
  1257. def test_utime(self):
  1258. self.assertRaises(OSError, os.utime, support.TESTFN, None)
  1259. def test_chmod(self):
  1260. self.assertRaises(OSError, os.chmod, support.TESTFN, 0)
  1261. class TestInvalidFD(unittest.TestCase):
  1262. singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat",
  1263. "fstatvfs", "fsync", "tcgetpgrp", "ttyname"]
  1264. #singles.append("close")
  1265. #We omit close because it doesn'r raise an exception on some platforms
  1266. def get_single(f):
  1267. def helper(self):
  1268. if hasattr(os, f):
  1269. self.check(getattr(os, f))
  1270. return helper
  1271. for f in singles:
  1272. locals()["test_"+f] = get_single(f)
  1273. def check(self, f, *args):
  1274. try:
  1275. f(support.make_bad_fd(), *args)
  1276. except OSError as e:
  1277. self.assertEqual(e.errno, errno.EBADF)
  1278. else:
  1279. self.fail("%r didn't raise an OSError with a bad file descriptor"
  1280. % f)
  1281. @unittest.skipUnless(hasattr(os, 'isatty'), 'test needs os.isatty()')
  1282. def test_isatty(self):
  1283. self.assertEqual(os.isatty(support.make_bad_fd()), False)
  1284. @unittest.skipUnless(hasattr(os, 'closerange'), 'test needs os.closerange()')
  1285. def test_closerange(self):
  1286. fd = support.make_bad_fd()
  1287. # Make sure none of the descriptors we are about to close are
  1288. # currently valid (issue 6542).
  1289. for i in range(10):
  1290. try: os.fstat(fd+i)
  1291. except OSError:
  1292. pass
  1293. else:
  1294. break
  1295. if i < 2:
  1296. raise unittest.SkipTest(
  1297. "Unable to acquire a range of invalid file descriptors")
  1298. self.assertEqual(os.closerange(fd, fd + i-1), None)
  1299. @unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()')
  1300. def test_dup2(self):
  1301. self.check(os.dup2, 20)
  1302. @unittest.skipUnless(hasattr(os, 'fchmod'), 'test needs os.fchmod()')
  1303. def test_fchmod(self):
  1304. self.check(os.fchmod, 0)
  1305. @unittest.skipUnless(hasattr(os, 'fchown'), 'test needs os.fchown()')
  1306. def test_fchown(self):
  1307. self.check(os.fchown, -1, -1)
  1308. @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()')
  1309. def test_fpathconf(self):
  1310. self.check(os.pathconf, "PC_NAME_MAX")
  1311. self.check(os.fpathconf, "PC_NAME_MAX")
  1312. @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
  1313. def test_ftruncate(self):
  1314. self.check(os.truncate, 0)
  1315. self.check(os.ftruncate, 0)
  1316. @unittest.skipUnless(hasattr(os, 'lseek'), 'test needs os.lseek()')
  1317. def test_lseek(self):
  1318. self.check(os.lseek, 0, 0)
  1319. @unittest.skipUnless(hasattr(os, 'read'), 'test needs os.read()')
  1320. def test_read(self):
  1321. self.check(os.read, 1)
  1322. @unittest.skipUnless(hasattr(os, 'readv'), 'test needs os.readv()')
  1323. def test_readv(self):
  1324. buf = bytearray(10)
  1325. self.check(os.readv, [buf])
  1326. @unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()')
  1327. def test_tcsetpgrpt(self):
  1328. self.check(os.tcsetpgrp, 0)
  1329. @unittest.skipUnless(hasattr(os, 'write'), 'test needs os.write()')
  1330. def test_write(self):
  1331. self.check(os.write, b" ")
  1332. @unittest.skipUnless(hasattr(os, 'writev'), 'test needs os.writev()')
  1333. def test_writev(self):
  1334. self.check(os.writev, [b'abc'])
  1335. def test_inheritable(self):
  1336. self.check(os.get_inheritable)
  1337. self.check(os.set_inheritable, True)
  1338. @unittest.skipUnless(hasattr(os, 'get_blocking'),
  1339. 'needs os.get_blocking() and os.set_blocking()')
  1340. def test_blocking(self):
  1341. self.check(os.get_blocking)
  1342. self.check(os.set_blocking, True)
  1343. class LinkTests(unittest.TestCase):
  1344. def setUp(self):
  1345. self.file1 = support.TESTFN
  1346. self.file2 = os.path.join(support.TESTFN + "2")
  1347. def tearDown(self):
  1348. for file in (self.file1, self.file2):
  1349. if os.path.exists(file):
  1350. os.unlink(file)
  1351. def _test_link(self, file1, file2):
  1352. create_file(file1)
  1353. with bytes_filename_warn(False):
  1354. os.link(file1, file2)
  1355. with open(file1, "r") as f1, open(file2, "r") as f2:
  1356. self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno()))
  1357. def test_link(self):
  1358. self._test_link(self.file1, self.file2)
  1359. def test_link_bytes(self):
  1360. self._test_link(bytes(self.file1, sys.getfilesystemencoding()),
  1361. bytes(self.file2, sys.getfilesystemencoding()))
  1362. def test_unicode_name(self):
  1363. try:
  1364. os.fsencode("\xf1")
  1365. except UnicodeError:
  1366. raise unittest.SkipTest("Unable to encode for this platform.")
  1367. self.file1 += "\xf1"
  1368. self.file2 = self.file1 + "2"
  1369. self._test_link(self.file1, self.file2)
  1370. @unittest.skipIf(sys.platform == "win32", "Posix specific tests")
  1371. class PosixUidGidTests(unittest.TestCase):
  1372. @unittest.skipUnless(hasattr(os, 'setuid'), 'test needs os.setuid()')
  1373. def test_setuid(self):
  1374. if os.getuid() != 0:
  1375. self.assertRaises(OSError, os.setuid, 0)
  1376. self.assertRaises(OverflowError, os.setuid, 1<<32)
  1377. @unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()')
  1378. def test_setgid(self):
  1379. if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
  1380. self.assertRaises(OSError, os.setgid, 0)
  1381. self.assertRaises(OverflowError, os.setgid, 1<<32)
  1382. @unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()')
  1383. def test_seteuid(self):
  1384. if os.getuid() != 0:
  1385. self.assertRaises(OSError, os.seteuid, 0)
  1386. self.assertRaises(OverflowError, os.seteuid, 1<<32)
  1387. @unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()')
  1388. def test_setegid(self):
  1389. if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
  1390. self.assertRaises(OSError, os.setegid, 0)
  1391. self.assertRaises(OverflowError, os.setegid, 1<<32)
  1392. @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
  1393. def test_setreuid(self):
  1394. if os.getuid() != 0:
  1395. self.assertRaises(OSError, os.setreuid, 0, 0)
  1396. self.assertRaises(OverflowError, os.setreuid, 1<<32, 0)
  1397. self.assertRaises(OverflowError, os.setreuid, 0, 1<<32)
  1398. @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
  1399. def test_setreuid_neg1(self):
  1400. # Needs to accept -1. We run this in a subprocess to avoid
  1401. # altering the test runner's process state (issue8045).
  1402. subprocess.check_call([
  1403. sys.executable, '-c',
  1404. 'import os,sys;os.setreuid(-1,-1);sys.exit(0)'])
  1405. @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
  1406. def test_setregid(self):
  1407. if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
  1408. self.assertRaises(OSError, os.setregid, 0, 0)
  1409. self.assertRaises(OverflowError, os.setregid, 1<<32, 0)
  1410. self.assertRaises(OverflowError, os.setregid, 0, 1<<32)
  1411. @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
  1412. def test_setregid_neg1(self):
  1413. # Needs to accept -1. We run this in a subprocess to avoid
  1414. # altering the test runner's process state (issue8045).
  1415. subprocess.check_call([
  1416. sys.executable, '-c',
  1417. 'import os,sys;os.setregid(-1,-1);sys.exit(0)'])
  1418. @unittest.skipIf(sys.platform == "win32", "Posix specific tests")
  1419. class Pep383Tests(unittest.TestCase):
  1420. def setUp(self):
  1421. if support.TESTFN_UNENCODABLE:
  1422. self.dir = support.TESTFN_UNENCODABLE
  1423. elif support.TESTFN_NONASCII:
  1424. self.dir = support.TESTFN_NONASCII
  1425. else:
  1426. self.dir = support.TESTFN
  1427. self.bdir = os.fsencode(self.dir)
  1428. bytesfn = []
  1429. def add_filename(fn):
  1430. try:
  1431. fn = os.fsencode(fn)
  1432. except UnicodeEncodeError:
  1433. return
  1434. bytesfn.append(fn)
  1435. add_filename(support.TESTFN_UNICODE)
  1436. if support.TESTFN_UNENCODABLE:
  1437. add_filename(support.TESTFN_UNENCODABLE)
  1438. if support.TESTFN_NONASCII:
  1439. add_filename(support.TESTFN_NONASCII)
  1440. if not bytesfn:
  1441. self.skipTest("couldn't create any non-ascii filename")
  1442. self.unicodefn = set()
  1443. os.mkdir(self.dir)
  1444. try:
  1445. for fn in bytesfn:
  1446. support.create_empty_file(os.path.join(self.bdir, fn))
  1447. fn = os.fsdecode(fn)
  1448. if fn in self.unicodefn:
  1449. raise ValueError("duplicate filename")
  1450. self.unicodefn.add(fn)
  1451. except:
  1452. shutil.rmtree(self.dir)
  1453. raise
  1454. def tearDown(self):
  1455. shutil.rmtree(self.dir)
  1456. def test_listdir(self):
  1457. expected = self.unicodefn
  1458. found = set(os.listdir(self.dir))
  1459. self.assertEqual(found, expected)
  1460. # test listdir without arguments
  1461. current_directory = os.getcwd()
  1462. try:
  1463. os.chdir(os.sep)
  1464. self.assertEqual(set(os.listdir()), set(os.listdir(os.sep)))
  1465. finally:
  1466. os.chdir(current_directory)
  1467. def test_open(self):
  1468. for fn in self.unicodefn:
  1469. f = open(os.path.join(self.dir, fn), 'rb')
  1470. f.close()
  1471. @unittest.skipUnless(hasattr(os, 'statvfs'),
  1472. "need os.statvfs()")
  1473. def test_statvfs(self):
  1474. # issue #9645
  1475. for fn in self.unicodefn:
  1476. # should not fail with file not found error
  1477. fullname = os.path.join(self.dir, fn)
  1478. os.statvfs(fullname)
  1479. def test_stat(self):
  1480. for fn in self.unicodefn:
  1481. os.stat(os.path.join(self.dir, fn))
  1482. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  1483. class Win32KillTests(unittest.TestCase):
  1484. def _kill(self, sig):
  1485. # Start sys.executable as a subprocess and communicate from the
  1486. # subprocess to the parent that the interpreter is ready. When it
  1487. # becomes ready, send *sig* via os.kill to the subprocess and check
  1488. # that the return code is equal to *sig*.
  1489. import ctypes
  1490. from ctypes import wintypes
  1491. import msvcrt
  1492. # Since we can't access the contents of the process' stdout until the
  1493. # process has exited, use PeekNamedPipe to see what's inside stdout
  1494. # without waiting. This is done so we can tell that the interpreter
  1495. # is started and running at a point where it could handle a signal.
  1496. PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
  1497. PeekNamedPipe.restype = wintypes.BOOL
  1498. PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle
  1499. ctypes.POINTER(ctypes.c_char), # stdout buf
  1500. wintypes.DWORD, # Buffer size
  1501. ctypes.POINTER(wintypes.DWORD), # bytes read
  1502. ctypes.POINTER(wintypes.DWORD), # bytes avail
  1503. ctypes.POINTER(wintypes.DWORD)) # bytes left
  1504. msg = "running"
  1505. proc = subprocess.Popen([sys.executable, "-c",
  1506. "import sys;"
  1507. "sys.stdout.write('{}');"
  1508. "sys.stdout.flush();"
  1509. "input()".format(msg)],
  1510. stdout=subprocess.PIPE,
  1511. stderr=subprocess.PIPE,
  1512. stdin=subprocess.PIPE)
  1513. self.addCleanup(proc.stdout.close)
  1514. self.addCleanup(proc.stderr.close)
  1515. self.addCleanup(proc.stdin.close)
  1516. count, max = 0, 100
  1517. while count < max and proc.poll() is None:
  1518. # Create a string buffer to store the result of stdout from the pipe
  1519. buf = ctypes.create_string_buffer(len(msg))
  1520. # Obtain the text currently in proc.stdout
  1521. # Bytes read/avail/left are left as NULL and unused
  1522. rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()),
  1523. buf, ctypes.sizeof(buf), None, None, None)
  1524. self.assertNotEqual(rslt, 0, "PeekNamedPipe failed")
  1525. if buf.value:
  1526. self.assertEqual(msg, buf.value.decode())
  1527. break
  1528. time.sleep(0.1)
  1529. count += 1
  1530. else:
  1531. self.fail("Did not receive communication from the subprocess")
  1532. os.kill(proc.pid, sig)
  1533. self.assertEqual(proc.wait(), sig)
  1534. def test_kill_sigterm(self):
  1535. # SIGTERM doesn't mean anything special, but make sure it works
  1536. self._kill(signal.SIGTERM)
  1537. def test_kill_int(self):
  1538. # os.kill on Windows can take an int which gets set as the exit code
  1539. self._kill(100)
  1540. def _kill_with_event(self, event, name):
  1541. tagname = "test_os_%s" % uuid.uuid1()
  1542. m = mmap.mmap(-1, 1, tagname)
  1543. m[0] = 0
  1544. # Run a script which has console control handling enabled.
  1545. proc = subprocess.Popen([sys.executable,
  1546. os.path.join(os.path.dirname(__file__),
  1547. "win_console_handler.py"), tagname],
  1548. creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
  1549. # Let the interpreter startup before we send signals. See #3137.
  1550. count, max = 0, 100
  1551. while count < max and proc.poll() is None:
  1552. if m[0] == 1:
  1553. break
  1554. time.sleep(0.1)
  1555. count += 1
  1556. else:
  1557. # Forcefully kill the process if we weren't able to signal it.
  1558. os.kill(proc.pid, signal.SIGINT)
  1559. self.fail("Subprocess didn't finish initialization")
  1560. os.kill(proc.pid, event)
  1561. # proc.send_signal(event) could also be done here.
  1562. # Allow time for the signal to be passed and the process to exit.
  1563. time.sleep(0.5)
  1564. if not proc.poll():
  1565. # Forcefully kill the process if we weren't able to signal it.
  1566. os.kill(proc.pid, signal.SIGINT)
  1567. self.fail("subprocess did not stop on {}".format(name))
  1568. @unittest.skip("subprocesses aren't inheriting Ctrl+C property")
  1569. def test_CTRL_C_EVENT(self):
  1570. from ctypes import wintypes
  1571. import ctypes
  1572. # Make a NULL value by creating a pointer with no argument.
  1573. NULL = ctypes.POINTER(ctypes.c_int)()
  1574. SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
  1575. SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int),
  1576. wintypes.BOOL)
  1577. SetConsoleCtrlHandler.restype = wintypes.BOOL
  1578. # Calling this with NULL and FALSE causes the calling process to
  1579. # handle Ctrl+C, rather than ignore it. This property is inherited
  1580. # by subprocesses.
  1581. SetConsoleCtrlHandler(NULL, 0)
  1582. self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT")
  1583. def test_CTRL_BREAK_EVENT(self):
  1584. self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
  1585. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  1586. class Win32ListdirTests(unittest.TestCase):
  1587. """Test listdir on Windows."""
  1588. def setUp(self):
  1589. self.created_paths = []
  1590. for i in range(2):
  1591. dir_name = 'SUB%d' % i
  1592. dir_path = os.path.join(support.TESTFN, dir_name)
  1593. file_name = 'FILE%d' % i
  1594. file_path = os.path.join(support.TESTFN, file_name)
  1595. os.makedirs(dir_path)
  1596. with open(file_path, 'w') as f:
  1597. f.write("I'm %s and proud of it. Blame test_os.\n" % file_path)
  1598. self.created_paths.extend([dir_name, file_name])
  1599. self.created_paths.sort()
  1600. def tearDown(self):
  1601. shutil.rmtree(support.TESTFN)
  1602. def test_listdir_no_extended_path(self):
  1603. """Test when the path is not an "extended" path."""
  1604. # unicode
  1605. self.assertEqual(
  1606. sorted(os.listdir(support.TESTFN)),
  1607. self.created_paths)
  1608. # bytes
  1609. with bytes_filename_warn(False):
  1610. self.assertEqual(
  1611. sorted(os.listdir(os.fsencode(support.TESTFN))),
  1612. [os.fsencode(path) for path in self.created_paths])
  1613. def test_listdir_extended_path(self):
  1614. """Test when the path starts with '\\\\?\\'."""
  1615. # See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
  1616. # unicode
  1617. path = '\\\\?\\' + os.path.abspath(support.TESTFN)
  1618. self.assertEqual(
  1619. sorted(os.listdir(path)),
  1620. self.created_paths)
  1621. # bytes
  1622. with bytes_filename_warn(False):
  1623. path = b'\\\\?\\' + os.fsencode(os.path.abspath(support.TESTFN))
  1624. self.assertEqual(
  1625. sorted(os.listdir(path)),
  1626. [os.fsencode(path) for path in self.created_paths])
  1627. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  1628. @support.skip_unless_symlink
  1629. class Win32SymlinkTests(unittest.TestCase):
  1630. filelink = 'filelinktest'
  1631. filelink_target = os.path.abspath(__file__)
  1632. dirlink = 'dirlinktest'
  1633. dirlink_target = os.path.dirname(filelink_target)
  1634. missing_link = 'missing link'
  1635. def setUp(self):
  1636. assert os.path.exists(self.dirlink_target)
  1637. assert os.path.exists(self.filelink_target)
  1638. assert not os.path.exists(self.dirlink)
  1639. assert not os.path.exists(self.filelink)
  1640. assert not os.path.exists(self.missing_link)
  1641. def tearDown(self):
  1642. if os.path.exists(self.filelink):
  1643. os.remove(self.filelink)
  1644. if os.path.exists(self.dirlink):
  1645. os.rmdir(self.dirlink)
  1646. if os.path.lexists(self.missing_link):
  1647. os.remove(self.missing_link)
  1648. def test_directory_link(self):
  1649. os.symlink(self.dirlink_target, self.dirlink)
  1650. self.assertTrue(os.path.exists(self.dirlink))
  1651. self.assertTrue(os.path.isdir(self.dirlink))
  1652. self.assertTrue(os.path.islink(self.dirlink))
  1653. self.check_stat(self.dirlink, self.dirlink_target)
  1654. def test_file_link(self):
  1655. os.symlink(self.filelink_target, self.filelink)
  1656. self.assertTrue(os.path.exists(self.filelink))
  1657. self.assertTrue(os.path.isfile(self.filelink))
  1658. self.assertTrue(os.path.islink(self.filelink))
  1659. self.check_stat(self.filelink, self.filelink_target)
  1660. def _create_missing_dir_link(self):
  1661. 'Create a "directory" link to a non-existent target'
  1662. linkname = self.missing_link
  1663. if os.path.lexists(linkname):
  1664. os.remove(linkname)
  1665. target = r'c:\\target does not exist.29r3c740'
  1666. assert not os.path.exists(target)
  1667. target_is_dir = True
  1668. os.symlink(target, linkname, target_is_dir)
  1669. def test_remove_directory_link_to_missing_target(self):
  1670. self._create_missing_dir_link()
  1671. # For compatibility with Unix, os.remove will check the
  1672. # directory status and call RemoveDirectory if the symlink
  1673. # was created with target_is_dir==True.
  1674. os.remove(self.missing_link)
  1675. @unittest.skip("currently fails; consider for improvement")
  1676. def test_isdir_on_directory_link_to_missing_target(self):
  1677. self._create_missing_dir_link()
  1678. # consider having isdir return true for directory links
  1679. self.assertTrue(os.path.isdir(self.missing_link))
  1680. @unittest.skip("currently fails; consider for improvement")
  1681. def test_rmdir_on_directory_link_to_missing_target(self):
  1682. self._create_missing_dir_link()
  1683. # consider allowing rmdir to remove directory links
  1684. os.rmdir(self.missing_link)
  1685. def check_stat(self, link, target):
  1686. self.assertEqual(os.stat(link), os.stat(target))
  1687. self.assertNotEqual(os.lstat(link), os.stat(link))
  1688. bytes_link = os.fsencode(link)
  1689. with bytes_filename_warn(True):
  1690. self.assertEqual(os.stat(bytes_link), os.stat(target))
  1691. with bytes_filename_warn(True):
  1692. self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link))
  1693. def test_12084(self):
  1694. level1 = os.path.abspath(support.TESTFN)
  1695. level2 = os.path.join(level1, "level2")
  1696. level3 = os.path.join(level2, "level3")
  1697. self.addCleanup(support.rmtree, level1)
  1698. os.mkdir(level1)
  1699. os.mkdir(level2)
  1700. os.mkdir(level3)
  1701. file1 = os.path.abspath(os.path.join(level1, "file1"))
  1702. create_file(file1)
  1703. orig_dir = os.getcwd()
  1704. try:
  1705. os.chdir(level2)
  1706. link = os.path.join(level2, "link")
  1707. os.symlink(os.path.relpath(file1), "link")
  1708. self.assertIn("link", os.listdir(os.getcwd()))
  1709. # Check os.stat calls from the same dir as the link
  1710. self.assertEqual(os.stat(file1), os.stat("link"))
  1711. # Check os.stat calls from a dir below the link
  1712. os.chdir(level1)
  1713. self.assertEqual(os.stat(file1),
  1714. os.stat(os.path.relpath(link)))
  1715. # Check os.stat calls from a dir above the link
  1716. os.chdir(level3)
  1717. self.assertEqual(os.stat(file1),
  1718. os.stat(os.path.relpath(link)))
  1719. finally:
  1720. os.chdir(orig_dir)
  1721. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  1722. class Win32JunctionTests(unittest.TestCase):
  1723. junction = 'junctiontest'
  1724. junction_target = os.path.dirname(os.path.abspath(__file__))
  1725. def setUp(self):
  1726. assert os.path.exists(self.junction_target)
  1727. assert not os.path.exists(self.junction)
  1728. def tearDown(self):
  1729. if os.path.exists(self.junction):
  1730. # os.rmdir delegates to Windows' RemoveDirectoryW,
  1731. # which removes junction points safely.
  1732. os.rmdir(self.junction)
  1733. def test_create_junction(self):
  1734. _winapi.CreateJunction(self.junction_target, self.junction)
  1735. self.assertTrue(os.path.exists(self.junction))
  1736. self.assertTrue(os.path.isdir(self.junction))
  1737. # Junctions are not recognized as links.
  1738. self.assertFalse(os.path.islink(self.junction))
  1739. def test_unlink_removes_junction(self):
  1740. _winapi.CreateJunction(self.junction_target, self.junction)
  1741. self.assertTrue(os.path.exists(self.junction))
  1742. os.unlink(self.junction)
  1743. self.assertFalse(os.path.exists(self.junction))
  1744. @support.skip_unless_symlink
  1745. class NonLocalSymlinkTests(unittest.TestCase):
  1746. def setUp(self):
  1747. """
  1748. Create this structure:
  1749. base
  1750. \___ some_dir
  1751. """
  1752. os.makedirs('base/some_dir')
  1753. def tearDown(self):
  1754. shutil.rmtree('base')
  1755. def test_directory_link_nonlocal(self):
  1756. """
  1757. The symlink target should resolve relative to the link, not relative
  1758. to the current directory.
  1759. Then, link base/some_link -> base/some_dir and ensure that some_link
  1760. is resolved as a directory.
  1761. In issue13772, it was discovered that directory detection failed if
  1762. the symlink target was not specified relative to the current
  1763. directory, which was a defect in the implementation.
  1764. """
  1765. src = os.path.join('base', 'some_link')
  1766. os.symlink('some_dir', src)
  1767. assert os.path.isdir(src)
  1768. class FSEncodingTests(unittest.TestCase):
  1769. def test_nop(self):
  1770. self.assertEqual(os.fsencode(b'abc\xff'), b'abc\xff')
  1771. self.assertEqual(os.fsdecode('abc\u0141'), 'abc\u0141')
  1772. def test_identity(self):
  1773. # assert fsdecode(fsencode(x)) == x
  1774. for fn in ('unicode\u0141', 'latin\xe9', 'ascii'):
  1775. try:
  1776. bytesfn = os.fsencode(fn)
  1777. except UnicodeEncodeError:
  1778. continue
  1779. self.assertEqual(os.fsdecode(bytesfn), fn)
  1780. class DeviceEncodingTests(unittest.TestCase):
  1781. def test_bad_fd(self):
  1782. # Return None when an fd doesn't actually exist.
  1783. self.assertIsNone(os.device_encoding(123456))
  1784. @unittest.skipUnless(os.isatty(0) and (sys.platform.startswith('win') or
  1785. (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))),
  1786. 'test requires a tty and either Windows or nl_langinfo(CODESET)')
  1787. def test_device_encoding(self):
  1788. encoding = os.device_encoding(0)
  1789. self.assertIsNotNone(encoding)
  1790. self.assertTrue(codecs.lookup(encoding))
  1791. class PidTests(unittest.TestCase):
  1792. @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
  1793. def test_getppid(self):
  1794. p = subprocess.Popen([sys.executable, '-c',
  1795. 'import os; print(os.getppid())'],
  1796. stdout=subprocess.PIPE)
  1797. stdout, _ = p.communicate()
  1798. # We are the parent of our subprocess
  1799. self.assertEqual(int(stdout), os.getpid())
  1800. def test_waitpid(self):
  1801. args = [sys.executable, '-c', 'pass']
  1802. pid = os.spawnv(os.P_NOWAIT, args[0], args)
  1803. status = os.waitpid(pid, 0)
  1804. self.assertEqual(status, (pid, 0))
  1805. # The introduction of this TestCase caused at least two different errors on
  1806. # *nix buildbots. Temporarily skip this to let the buildbots move along.
  1807. @unittest.skip("Skip due to platform/environment differences on *NIX buildbots")
  1808. @unittest.skipUnless(hasattr(os, 'getlogin'), "test needs os.getlogin")
  1809. class LoginTests(unittest.TestCase):
  1810. def test_getlogin(self):
  1811. user_name = os.getlogin()
  1812. self.assertNotEqual(len(user_name), 0)
  1813. @unittest.skipUnless(hasattr(os, 'getpriority') and hasattr(os, 'setpriority'),
  1814. "needs os.getpriority and os.setpriority")
  1815. class ProgramPriorityTests(unittest.TestCase):
  1816. """Tests for os.getpriority() and os.setpriority()."""
  1817. def test_set_get_priority(self):
  1818. base = os.getpriority(os.PRIO_PROCESS, os.getpid())
  1819. os.setpriority(os.PRIO_PROCESS, os.getpid(), base + 1)
  1820. try:
  1821. new_prio = os.getpriority(os.PRIO_PROCESS, os.getpid())
  1822. if base >= 19 and new_prio <= 19:
  1823. raise unittest.SkipTest("unable to reliably test setpriority "
  1824. "at current nice level of %s" % base)
  1825. else:
  1826. self.assertEqual(new_prio, base + 1)
  1827. finally:
  1828. try:
  1829. os.setpriority(os.PRIO_PROCESS, os.getpid(), base)
  1830. except OSError as err:
  1831. if err.errno != errno.EACCES:
  1832. raise
  1833. if threading is not None:
  1834. class SendfileTestServer(asyncore.dispatcher, threading.Thread):
  1835. class Handler(asynchat.async_chat):
  1836. def __init__(self, conn):
  1837. asynchat.async_chat.__init__(self, conn)
  1838. self.in_buffer = []
  1839. self.closed = False
  1840. self.push(b"220 ready\r\n")
  1841. def handle_read(self):
  1842. data = self.recv(4096)
  1843. self.in_buffer.append(data)
  1844. def get_data(self):
  1845. return b''.join(self.in_buffer)
  1846. def handle_close(self):
  1847. self.close()
  1848. self.closed = True
  1849. def handle_error(self):
  1850. raise
  1851. def __init__(self, address):
  1852. threading.Thread.__init__(self)
  1853. asyncore.dispatcher.__init__(self)
  1854. self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  1855. self.bind(address)
  1856. self.listen(5)
  1857. self.host, self.port = self.socket.getsockname()[:2]
  1858. self.handler_instance = None
  1859. self._active = False
  1860. self._active_lock = threading.Lock()
  1861. # --- public API
  1862. @property
  1863. def running(self):
  1864. return self._active
  1865. def start(self):
  1866. assert not self.running
  1867. self.__flag = threading.Event()
  1868. threading.Thread.start(self)
  1869. self.__flag.wait()
  1870. def stop(self):
  1871. assert self.running
  1872. self._active = False
  1873. self.join()
  1874. def wait(self):
  1875. # wait for handler connection to be closed, then stop the server
  1876. while not getattr(self.handler_instance, "closed", False):
  1877. time.sleep(0.001)
  1878. self.stop()
  1879. # --- internals
  1880. def run(self):
  1881. self._active = True
  1882. self.__flag.set()
  1883. while self._active and asyncore.socket_map:
  1884. self._active_lock.acquire()
  1885. asyncore.loop(timeout=0.001, count=1)
  1886. self._active_lock.release()
  1887. asyncore.close_all()
  1888. def handle_accept(self):
  1889. conn, addr = self.accept()
  1890. self.handler_instance = self.Handler(conn)
  1891. def handle_connect(self):
  1892. self.close()
  1893. handle_read = handle_connect
  1894. def writable(self):
  1895. return 0
  1896. def handle_error(self):
  1897. raise
  1898. @unittest.skipUnless(threading is not None, "test needs threading module")
  1899. @unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()")
  1900. class TestSendfile(unittest.TestCase):
  1901. DATA = b"12345abcde" * 16 * 1024 # 160 KB
  1902. SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \
  1903. not sys.platform.startswith("solaris") and \
  1904. not sys.platform.startswith("sunos")
  1905. requires_headers_trailers = unittest.skipUnless(SUPPORT_HEADERS_TRAILERS,
  1906. 'requires headers and trailers support')
  1907. @classmethod
  1908. def setUpClass(cls):
  1909. cls.key = support.threading_setup()
  1910. create_file(support.TESTFN, cls.DATA)
  1911. @classmethod
  1912. def tearDownClass(cls):
  1913. support.threading_cleanup(*cls.key)
  1914. support.unlink(support.TESTFN)
  1915. def setUp(self):
  1916. self.server = SendfileTestServer((support.HOST, 0))
  1917. self.server.start()
  1918. self.client = socket.socket()
  1919. self.client.connect((self.server.host, self.server.port))
  1920. self.client.settimeout(1)
  1921. # synchronize by waiting for "220 ready" response
  1922. self.client.recv(1024)
  1923. self.sockno = self.client.fileno()
  1924. self.file = open(support.TESTFN, 'rb')
  1925. self.fileno = self.file.fileno()
  1926. def tearDown(self):
  1927. self.file.close()
  1928. self.client.close()
  1929. if self.server.running:
  1930. self.server.stop()
  1931. def sendfile_wrapper(self, sock, file, offset, nbytes, headers=[], trailers=[]):
  1932. """A higher level wrapper representing how an application is
  1933. supposed to use sendfile().
  1934. """
  1935. while 1:
  1936. try:
  1937. if self.SUPPORT_HEADERS_TRAILERS:
  1938. return os.sendfile(sock, file, offset, nbytes, headers,
  1939. trailers)
  1940. else:
  1941. return os.sendfile(sock, file, offset, nbytes)
  1942. except OSError as err:
  1943. if err.errno == errno.ECONNRESET:
  1944. # disconnected
  1945. raise
  1946. elif err.errno in (errno.EAGAIN, errno.EBUSY):
  1947. # we have to retry send data
  1948. continue
  1949. else:
  1950. raise
  1951. def test_send_whole_file(self):
  1952. # normal send
  1953. total_sent = 0
  1954. offset = 0
  1955. nbytes = 4096
  1956. while total_sent < len(self.DATA):
  1957. sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
  1958. if sent == 0:
  1959. break
  1960. offset += sent
  1961. total_sent += sent
  1962. self.assertTrue(sent <= nbytes)
  1963. self.assertEqual(offset, total_sent)
  1964. self.assertEqual(total_sent, len(self.DATA))
  1965. self.client.shutdown(socket.SHUT_RDWR)
  1966. self.client.close()
  1967. self.server.wait()
  1968. data = self.server.handler_instance.get_data()
  1969. self.assertEqual(len(data), len(self.DATA))
  1970. self.assertEqual(data, self.DATA)
  1971. def test_send_at_certain_offset(self):
  1972. # start sending a file at a certain offset
  1973. total_sent = 0
  1974. offset = len(self.DATA) // 2
  1975. must_send = len(self.DATA) - offset
  1976. nbytes = 4096
  1977. while total_sent < must_send:
  1978. sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
  1979. if sent == 0:
  1980. break
  1981. offset += sent
  1982. total_sent += sent
  1983. self.assertTrue(sent <= nbytes)
  1984. self.client.shutdown(socket.SHUT_RDWR)
  1985. self.client.close()
  1986. self.server.wait()
  1987. data = self.server.handler_instance.get_data()
  1988. expected = self.DATA[len(self.DATA) // 2:]
  1989. self.assertEqual(total_sent, len(expected))
  1990. self.assertEqual(len(data), len(expected))
  1991. self.assertEqual(data, expected)
  1992. def test_offset_overflow(self):
  1993. # specify an offset > file size
  1994. offset = len(self.DATA) + 4096
  1995. try:
  1996. sent = os.sendfile(self.sockno, self.fileno, offset, 4096)
  1997. except OSError as e:
  1998. # Solaris can raise EINVAL if offset >= file length, ignore.
  1999. if e.errno != errno.EINVAL:
  2000. raise
  2001. else:
  2002. self.assertEqual(sent, 0)
  2003. self.client.shutdown(socket.SHUT_RDWR)
  2004. self.client.close()
  2005. self.server.wait()
  2006. data = self.server.handler_instance.get_data()
  2007. self.assertEqual(data, b'')
  2008. def test_invalid_offset(self):
  2009. with self.assertRaises(OSError) as cm:
  2010. os.sendfile(self.sockno, self.fileno, -1, 4096)
  2011. self.assertEqual(cm.exception.errno, errno.EINVAL)
  2012. def test_keywords(self):
  2013. # Keyword arguments should be supported
  2014. os.sendfile(out=self.sockno, offset=0, count=4096,
  2015. **{'in': self.fileno})
  2016. if self.SUPPORT_HEADERS_TRAILERS:
  2017. os.sendfile(self.sockno, self.fileno, offset=0, count=4096,
  2018. headers=(), trailers=(), flags=0)
  2019. # --- headers / trailers tests
  2020. @requires_headers_trailers
  2021. def test_headers(self):
  2022. total_sent = 0
  2023. sent = os.sendfile(self.sockno, self.fileno, 0, 4096,
  2024. headers=[b"x" * 512])
  2025. total_sent += sent
  2026. offset = 4096
  2027. nbytes = 4096
  2028. while 1:
  2029. sent = self.sendfile_wrapper(self.sockno, self.fileno,
  2030. offset, nbytes)
  2031. if sent == 0:
  2032. break
  2033. total_sent += sent
  2034. offset += sent
  2035. expected_data = b"x" * 512 + self.DATA
  2036. self.assertEqual(total_sent, len(expected_data))
  2037. self.client.close()
  2038. self.server.wait()
  2039. data = self.server.handler_instance.get_data()
  2040. self.assertEqual(hash(data), hash(expected_data))
  2041. @requires_headers_trailers
  2042. def test_trailers(self):
  2043. TESTFN2 = support.TESTFN + "2"
  2044. file_data = b"abcdef"
  2045. self.addCleanup(support.unlink, TESTFN2)
  2046. create_file(TESTFN2, file_data)
  2047. with open(TESTFN2, 'rb') as f:
  2048. os.sendfile(self.sockno, f.fileno(), 0, len(file_data),
  2049. trailers=[b"1234"])
  2050. self.client.close()
  2051. self.server.wait()
  2052. data = self.server.handler_instance.get_data()
  2053. self.assertEqual(data, b"abcdef1234")
  2054. @requires_headers_trailers
  2055. @unittest.skipUnless(hasattr(os, 'SF_NODISKIO'),
  2056. 'test needs os.SF_NODISKIO')
  2057. def test_flags(self):
  2058. try:
  2059. os.sendfile(self.sockno, self.fileno, 0, 4096,
  2060. flags=os.SF_NODISKIO)
  2061. except OSError as err:
  2062. if err.errno not in (errno.EBUSY, errno.EAGAIN):
  2063. raise
  2064. def supports_extended_attributes():
  2065. if not hasattr(os, "setxattr"):
  2066. return False
  2067. try:
  2068. with open(support.TESTFN, "xb", 0) as fp:
  2069. try:
  2070. os.setxattr(fp.fileno(), b"user.test", b"")
  2071. except OSError:
  2072. return False
  2073. finally:
  2074. support.unlink(support.TESTFN)
  2075. return True
  2076. @unittest.skipUnless(supports_extended_attributes(),
  2077. "no non-broken extended attribute support")
  2078. # Kernels < 2.6.39 don't respect setxattr flags.
  2079. @support.requires_linux_version(2, 6, 39)
  2080. class ExtendedAttributeTests(unittest.TestCase):
  2081. def _check_xattrs_str(self, s, getxattr, setxattr, removexattr, listxattr, **kwargs):
  2082. fn = support.TESTFN
  2083. self.addCleanup(support.unlink, fn)
  2084. create_file(fn)
  2085. with self.assertRaises(OSError) as cm:
  2086. getxattr(fn, s("user.test"), **kwargs)
  2087. self.assertEqual(cm.exception.errno, errno.ENODATA)
  2088. init_xattr = listxattr(fn)
  2089. self.assertIsInstance(init_xattr, list)
  2090. setxattr(fn, s("user.test"), b"", **kwargs)
  2091. xattr = set(init_xattr)
  2092. xattr.add("user.test")
  2093. self.assertEqual(set(listxattr(fn)), xattr)
  2094. self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"")
  2095. setxattr(fn, s("user.test"), b"hello", os.XATTR_REPLACE, **kwargs)
  2096. self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"hello")
  2097. with self.assertRaises(OSError) as cm:
  2098. setxattr(fn, s("user.test"), b"bye", os.XATTR_CREATE, **kwargs)
  2099. self.assertEqual(cm.exception.errno, errno.EEXIST)
  2100. with self.assertRaises(OSError) as cm:
  2101. setxattr(fn, s("user.test2"), b"bye", os.XATTR_REPLACE, **kwargs)
  2102. self.assertEqual(cm.exception.errno, errno.ENODATA)
  2103. setxattr(fn, s("user.test2"), b"foo", os.XATTR_CREATE, **kwargs)
  2104. xattr.add("user.test2")
  2105. self.assertEqual(set(listxattr(fn)), xattr)
  2106. removexattr(fn, s("user.test"), **kwargs)
  2107. with self.assertRaises(OSError) as cm:
  2108. getxattr(fn, s("user.test"), **kwargs)
  2109. self.assertEqual(cm.exception.errno, errno.ENODATA)
  2110. xattr.remove("user.test")
  2111. self.assertEqual(set(listxattr(fn)), xattr)
  2112. self.assertEqual(getxattr(fn, s("user.test2"), **kwargs), b"foo")
  2113. setxattr(fn, s("user.test"), b"a"*1024, **kwargs)
  2114. self.assertEqual(getxattr(fn, s("user.test"), **kwargs), b"a"*1024)
  2115. removexattr(fn, s("user.test"), **kwargs)
  2116. many = sorted("user.test{}".format(i) for i in range(100))
  2117. for thing in many:
  2118. setxattr(fn, thing, b"x", **kwargs)
  2119. self.assertEqual(set(listxattr(fn)), set(init_xattr) | set(many))
  2120. def _check_xattrs(self, *args, **kwargs):
  2121. self._check_xattrs_str(str, *args, **kwargs)
  2122. support.unlink(support.TESTFN)
  2123. self._check_xattrs_str(os.fsencode, *args, **kwargs)
  2124. support.unlink(support.TESTFN)
  2125. def test_simple(self):
  2126. self._check_xattrs(os.getxattr, os.setxattr, os.removexattr,
  2127. os.listxattr)
  2128. def test_lpath(self):
  2129. self._check_xattrs(os.getxattr, os.setxattr, os.removexattr,
  2130. os.listxattr, follow_symlinks=False)
  2131. def test_fds(self):
  2132. def getxattr(path, *args):
  2133. with open(path, "rb") as fp:
  2134. return os.getxattr(fp.fileno(), *args)
  2135. def setxattr(path, *args):
  2136. with open(path, "wb", 0) as fp:
  2137. os.setxattr(fp.fileno(), *args)
  2138. def removexattr(path, *args):
  2139. with open(path, "wb", 0) as fp:
  2140. os.removexattr(fp.fileno(), *args)
  2141. def listxattr(path, *args):
  2142. with open(path, "rb") as fp:
  2143. return os.listxattr(fp.fileno(), *args)
  2144. self._check_xattrs(getxattr, setxattr, removexattr, listxattr)
  2145. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  2146. class Win32DeprecatedBytesAPI(unittest.TestCase):
  2147. def test_deprecated(self):
  2148. import nt
  2149. filename = os.fsencode(support.TESTFN)
  2150. for func, *args in (
  2151. (nt._getfullpathname, filename),
  2152. (nt._isdir, filename),
  2153. (os.access, filename, os.R_OK),
  2154. (os.chdir, filename),
  2155. (os.chmod, filename, 0o777),
  2156. (os.getcwdb,),
  2157. (os.link, filename, filename),
  2158. (os.listdir, filename),
  2159. (os.lstat, filename),
  2160. (os.mkdir, filename),
  2161. (os.open, filename, os.O_RDONLY),
  2162. (os.rename, filename, filename),
  2163. (os.rmdir, filename),
  2164. (os.startfile, filename),
  2165. (os.stat, filename),
  2166. (os.unlink, filename),
  2167. (os.utime, filename),
  2168. ):
  2169. with bytes_filename_warn(True):
  2170. try:
  2171. func(*args)
  2172. except OSError:
  2173. # ignore OSError, we only care about DeprecationWarning
  2174. pass
  2175. @support.skip_unless_symlink
  2176. def test_symlink(self):
  2177. self.addCleanup(support.unlink, support.TESTFN)
  2178. filename = os.fsencode(support.TESTFN)
  2179. with bytes_filename_warn(True):
  2180. os.symlink(filename, filename)
  2181. @unittest.skipUnless(hasattr(os, 'get_terminal_size'), "requires os.get_terminal_size")
  2182. class TermsizeTests(unittest.TestCase):
  2183. def test_does_not_crash(self):
  2184. """Check if get_terminal_size() returns a meaningful value.
  2185. There's no easy portable way to actually check the size of the
  2186. terminal, so let's check if it returns something sensible instead.
  2187. """
  2188. try:
  2189. size = os.get_terminal_size()
  2190. except OSError as e:
  2191. if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY):
  2192. # Under win32 a generic OSError can be thrown if the
  2193. # handle cannot be retrieved
  2194. self.skipTest("failed to query terminal size")
  2195. raise
  2196. self.assertGreaterEqual(size.columns, 0)
  2197. self.assertGreaterEqual(size.lines, 0)
  2198. def test_stty_match(self):
  2199. """Check if stty returns the same results
  2200. stty actually tests stdin, so get_terminal_size is invoked on
  2201. stdin explicitly. If stty succeeded, then get_terminal_size()
  2202. should work too.
  2203. """
  2204. try:
  2205. size = subprocess.check_output(['stty', 'size']).decode().split()
  2206. except (FileNotFoundError, subprocess.CalledProcessError):
  2207. self.skipTest("stty invocation failed")
  2208. expected = (int(size[1]), int(size[0])) # reversed order
  2209. try:
  2210. actual = os.get_terminal_size(sys.__stdin__.fileno())
  2211. except OSError as e:
  2212. if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY):
  2213. # Under win32 a generic OSError can be thrown if the
  2214. # handle cannot be retrieved
  2215. self.skipTest("failed to query terminal size")
  2216. raise
  2217. self.assertEqual(expected, actual)
  2218. class OSErrorTests(unittest.TestCase):
  2219. def setUp(self):
  2220. class Str(str):
  2221. pass
  2222. self.bytes_filenames = []
  2223. self.unicode_filenames = []
  2224. if support.TESTFN_UNENCODABLE is not None:
  2225. decoded = support.TESTFN_UNENCODABLE
  2226. else:
  2227. decoded = support.TESTFN
  2228. self.unicode_filenames.append(decoded)
  2229. self.unicode_filenames.append(Str(decoded))
  2230. if support.TESTFN_UNDECODABLE is not None:
  2231. encoded = support.TESTFN_UNDECODABLE
  2232. else:
  2233. encoded = os.fsencode(support.TESTFN)
  2234. self.bytes_filenames.append(encoded)
  2235. self.bytes_filenames.append(bytearray(encoded))
  2236. self.bytes_filenames.append(memoryview(encoded))
  2237. self.filenames = self.bytes_filenames + self.unicode_filenames
  2238. def test_oserror_filename(self):
  2239. funcs = [
  2240. (self.filenames, os.chdir,),
  2241. (self.filenames, os.chmod, 0o777),
  2242. (self.filenames, os.lstat,),
  2243. (self.filenames, os.open, os.O_RDONLY),
  2244. (self.filenames, os.rmdir,),
  2245. (self.filenames, os.stat,),
  2246. (self.filenames, os.unlink,),
  2247. ]
  2248. if sys.platform == "win32":
  2249. funcs.extend((
  2250. (self.bytes_filenames, os.rename, b"dst"),
  2251. (self.bytes_filenames, os.replace, b"dst"),
  2252. (self.unicode_filenames, os.rename, "dst"),
  2253. (self.unicode_filenames, os.replace, "dst"),
  2254. # Issue #16414: Don't test undecodable names with listdir()
  2255. # because of a Windows bug.
  2256. #
  2257. # With the ANSI code page 932, os.listdir(b'\xe7') return an
  2258. # empty list (instead of failing), whereas os.listdir(b'\xff')
  2259. # raises a FileNotFoundError. It looks like a Windows bug:
  2260. # b'\xe7' directory does not exist, FindFirstFileA(b'\xe7')
  2261. # fails with ERROR_FILE_NOT_FOUND (2), instead of
  2262. # ERROR_PATH_NOT_FOUND (3).
  2263. (self.unicode_filenames, os.listdir,),
  2264. ))
  2265. else:
  2266. funcs.extend((
  2267. (self.filenames, os.listdir,),
  2268. (self.filenames, os.rename, "dst"),
  2269. (self.filenames, os.replace, "dst"),
  2270. ))
  2271. if hasattr(os, "chown"):
  2272. funcs.append((self.filenames, os.chown, 0, 0))
  2273. if hasattr(os, "lchown"):
  2274. funcs.append((self.filenames, os.lchown, 0, 0))
  2275. if hasattr(os, "truncate"):
  2276. funcs.append((self.filenames, os.truncate, 0))
  2277. if hasattr(os, "chflags"):
  2278. funcs.append((self.filenames, os.chflags, 0))
  2279. if hasattr(os, "lchflags"):
  2280. funcs.append((self.filenames, os.lchflags, 0))
  2281. if hasattr(os, "chroot"):
  2282. funcs.append((self.filenames, os.chroot,))
  2283. if hasattr(os, "link"):
  2284. if sys.platform == "win32":
  2285. funcs.append((self.bytes_filenames, os.link, b"dst"))
  2286. funcs.append((self.unicode_filenames, os.link, "dst"))
  2287. else:
  2288. funcs.append((self.filenames, os.link, "dst"))
  2289. if hasattr(os, "listxattr"):
  2290. funcs.extend((
  2291. (self.filenames, os.listxattr,),
  2292. (self.filenames, os.getxattr, "user.test"),
  2293. (self.filenames, os.setxattr, "user.test", b'user'),
  2294. (self.filenames, os.removexattr, "user.test"),
  2295. ))
  2296. if hasattr(os, "lchmod"):
  2297. funcs.append((self.filenames, os.lchmod, 0o777))
  2298. if hasattr(os, "readlink"):
  2299. if sys.platform == "win32":
  2300. funcs.append((self.unicode_filenames, os.readlink,))
  2301. else:
  2302. funcs.append((self.filenames, os.readlink,))
  2303. for filenames, func, *func_args in funcs:
  2304. for name in filenames:
  2305. try:
  2306. if isinstance(name, str):
  2307. func(name, *func_args)
  2308. elif isinstance(name, bytes):
  2309. with bytes_filename_warn(False):
  2310. func(name, *func_args)
  2311. else:
  2312. with self.assertWarnsRegex(DeprecationWarning, 'should be'):
  2313. func(name, *func_args)
  2314. except OSError as err:
  2315. self.assertIs(err.filename, name)
  2316. else:
  2317. self.fail("No exception thrown by {}".format(func))
  2318. class CPUCountTests(unittest.TestCase):
  2319. def test_cpu_count(self):
  2320. cpus = os.cpu_count()
  2321. if cpus is not None:
  2322. self.assertIsInstance(cpus, int)
  2323. self.assertGreater(cpus, 0)
  2324. else:
  2325. self.skipTest("Could not determine the number of CPUs")
  2326. class FDInheritanceTests(unittest.TestCase):
  2327. def test_get_set_inheritable(self):
  2328. fd = os.open(__file__, os.O_RDONLY)
  2329. self.addCleanup(os.close, fd)
  2330. self.assertEqual(os.get_inheritable(fd), False)
  2331. os.set_inheritable(fd, True)
  2332. self.assertEqual(os.get_inheritable(fd), True)
  2333. @unittest.skipIf(fcntl is None, "need fcntl")
  2334. def test_get_inheritable_cloexec(self):
  2335. fd = os.open(__file__, os.O_RDONLY)
  2336. self.addCleanup(os.close, fd)
  2337. self.assertEqual(os.get_inheritable(fd), False)
  2338. # clear FD_CLOEXEC flag
  2339. flags = fcntl.fcntl(fd, fcntl.F_GETFD)
  2340. flags &= ~fcntl.FD_CLOEXEC
  2341. fcntl.fcntl(fd, fcntl.F_SETFD, flags)
  2342. self.assertEqual(os.get_inheritable(fd), True)
  2343. @unittest.skipIf(fcntl is None, "need fcntl")
  2344. def test_set_inheritable_cloexec(self):
  2345. fd = os.open(__file__, os.O_RDONLY)
  2346. self.addCleanup(os.close, fd)
  2347. self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
  2348. fcntl.FD_CLOEXEC)
  2349. os.set_inheritable(fd, True)
  2350. self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
  2351. 0)
  2352. def test_open(self):
  2353. fd = os.open(__file__, os.O_RDONLY)
  2354. self.addCleanup(os.close, fd)
  2355. self.assertEqual(os.get_inheritable(fd), False)
  2356. @unittest.skipUnless(hasattr(os, 'pipe'), "need os.pipe()")
  2357. def test_pipe(self):
  2358. rfd, wfd = os.pipe()
  2359. self.addCleanup(os.close, rfd)
  2360. self.addCleanup(os.close, wfd)
  2361. self.assertEqual(os.get_inheritable(rfd), False)
  2362. self.assertEqual(os.get_inheritable(wfd), False)
  2363. def test_dup(self):
  2364. fd1 = os.open(__file__, os.O_RDONLY)
  2365. self.addCleanup(os.close, fd1)
  2366. fd2 = os.dup(fd1)
  2367. self.addCleanup(os.close, fd2)
  2368. self.assertEqual(os.get_inheritable(fd2), False)
  2369. @unittest.skipUnless(hasattr(os, 'dup2'), "need os.dup2()")
  2370. def test_dup2(self):
  2371. fd = os.open(__file__, os.O_RDONLY)
  2372. self.addCleanup(os.close, fd)
  2373. # inheritable by default
  2374. fd2 = os.open(__file__, os.O_RDONLY)
  2375. try:
  2376. os.dup2(fd, fd2)
  2377. self.assertEqual(os.get_inheritable(fd2), True)
  2378. finally:
  2379. os.close(fd2)
  2380. # force non-inheritable
  2381. fd3 = os.open(__file__, os.O_RDONLY)
  2382. try:
  2383. os.dup2(fd, fd3, inheritable=False)
  2384. self.assertEqual(os.get_inheritable(fd3), False)
  2385. finally:
  2386. os.close(fd3)
  2387. @unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
  2388. def test_openpty(self):
  2389. master_fd, slave_fd = os.openpty()
  2390. self.addCleanup(os.close, master_fd)
  2391. self.addCleanup(os.close, slave_fd)
  2392. self.assertEqual(os.get_inheritable(master_fd), False)
  2393. self.assertEqual(os.get_inheritable(slave_fd), False)
  2394. @unittest.skipUnless(hasattr(os, 'get_blocking'),
  2395. 'needs os.get_blocking() and os.set_blocking()')
  2396. class BlockingTests(unittest.TestCase):
  2397. def test_blocking(self):
  2398. fd = os.open(__file__, os.O_RDONLY)
  2399. self.addCleanup(os.close, fd)
  2400. self.assertEqual(os.get_blocking(fd), True)
  2401. os.set_blocking(fd, False)
  2402. self.assertEqual(os.get_blocking(fd), False)
  2403. os.set_blocking(fd, True)
  2404. self.assertEqual(os.get_blocking(fd), True)
  2405. class ExportsTests(unittest.TestCase):
  2406. def test_os_all(self):
  2407. self.assertIn('open', os.__all__)
  2408. self.assertIn('walk', os.__all__)
  2409. class TestScandir(unittest.TestCase):
  2410. check_no_resource_warning = support.check_no_resource_warning
  2411. def setUp(self):
  2412. self.path = os.path.realpath(support.TESTFN)
  2413. self.bytes_path = os.fsencode(self.path)
  2414. self.addCleanup(support.rmtree, self.path)
  2415. os.mkdir(self.path)
  2416. def create_file(self, name="file.txt"):
  2417. path = self.bytes_path if isinstance(name, bytes) else self.path
  2418. filename = os.path.join(path, name)
  2419. create_file(filename, b'python')
  2420. return filename
  2421. def get_entries(self, names):
  2422. entries = dict((entry.name, entry)
  2423. for entry in os.scandir(self.path))
  2424. self.assertEqual(sorted(entries.keys()), names)
  2425. return entries
  2426. def assert_stat_equal(self, stat1, stat2, skip_fields):
  2427. if skip_fields:
  2428. for attr in dir(stat1):
  2429. if not attr.startswith("st_"):
  2430. continue
  2431. if attr in ("st_dev", "st_ino", "st_nlink"):
  2432. continue
  2433. self.assertEqual(getattr(stat1, attr),
  2434. getattr(stat2, attr),
  2435. (stat1, stat2, attr))
  2436. else:
  2437. self.assertEqual(stat1, stat2)
  2438. def check_entry(self, entry, name, is_dir, is_file, is_symlink):
  2439. self.assertIsInstance(entry, os.DirEntry)
  2440. self.assertEqual(entry.name, name)
  2441. self.assertEqual(entry.path, os.path.join(self.path, name))
  2442. self.assertEqual(entry.inode(),
  2443. os.stat(entry.path, follow_symlinks=False).st_ino)
  2444. entry_stat = os.stat(entry.path)
  2445. self.assertEqual(entry.is_dir(),
  2446. stat.S_ISDIR(entry_stat.st_mode))
  2447. self.assertEqual(entry.is_file(),
  2448. stat.S_ISREG(entry_stat.st_mode))
  2449. self.assertEqual(entry.is_symlink(),
  2450. os.path.islink(entry.path))
  2451. entry_lstat = os.stat(entry.path, follow_symlinks=False)
  2452. self.assertEqual(entry.is_dir(follow_symlinks=False),
  2453. stat.S_ISDIR(entry_lstat.st_mode))
  2454. self.assertEqual(entry.is_file(follow_symlinks=False),
  2455. stat.S_ISREG(entry_lstat.st_mode))
  2456. self.assert_stat_equal(entry.stat(),
  2457. entry_stat,
  2458. os.name == 'nt' and not is_symlink)
  2459. self.assert_stat_equal(entry.stat(follow_symlinks=False),
  2460. entry_lstat,
  2461. os.name == 'nt')
  2462. def test_attributes(self):
  2463. link = hasattr(os, 'link')
  2464. symlink = support.can_symlink()
  2465. dirname = os.path.join(self.path, "dir")
  2466. os.mkdir(dirname)
  2467. filename = self.create_file("file.txt")
  2468. if link:
  2469. os.link(filename, os.path.join(self.path, "link_file.txt"))
  2470. if symlink:
  2471. os.symlink(dirname, os.path.join(self.path, "symlink_dir"),
  2472. target_is_directory=True)
  2473. os.symlink(filename, os.path.join(self.path, "symlink_file.txt"))
  2474. names = ['dir', 'file.txt']
  2475. if link:
  2476. names.append('link_file.txt')
  2477. if symlink:
  2478. names.extend(('symlink_dir', 'symlink_file.txt'))
  2479. entries = self.get_entries(names)
  2480. entry = entries['dir']
  2481. self.check_entry(entry, 'dir', True, False, False)
  2482. entry = entries['file.txt']
  2483. self.check_entry(entry, 'file.txt', False, True, False)
  2484. if link:
  2485. entry = entries['link_file.txt']
  2486. self.check_entry(entry, 'link_file.txt', False, True, False)
  2487. if symlink:
  2488. entry = entries['symlink_dir']
  2489. self.check_entry(entry, 'symlink_dir', True, False, True)
  2490. entry = entries['symlink_file.txt']
  2491. self.check_entry(entry, 'symlink_file.txt', False, True, True)
  2492. def get_entry(self, name):
  2493. path = self.bytes_path if isinstance(name, bytes) else self.path
  2494. entries = list(os.scandir(path))
  2495. self.assertEqual(len(entries), 1)
  2496. entry = entries[0]
  2497. self.assertEqual(entry.name, name)
  2498. return entry
  2499. def create_file_entry(self, name='file.txt'):
  2500. filename = self.create_file(name=name)
  2501. return self.get_entry(os.path.basename(filename))
  2502. def test_current_directory(self):
  2503. filename = self.create_file()
  2504. old_dir = os.getcwd()
  2505. try:
  2506. os.chdir(self.path)
  2507. # call scandir() without parameter: it must list the content
  2508. # of the current directory
  2509. entries = dict((entry.name, entry) for entry in os.scandir())
  2510. self.assertEqual(sorted(entries.keys()),
  2511. [os.path.basename(filename)])
  2512. finally:
  2513. os.chdir(old_dir)
  2514. def test_repr(self):
  2515. entry = self.create_file_entry()
  2516. self.assertEqual(repr(entry), "<DirEntry 'file.txt'>")
  2517. def test_fspath_protocol(self):
  2518. entry = self.create_file_entry()
  2519. self.assertEqual(os.fspath(entry), os.path.join(self.path, 'file.txt'))
  2520. @unittest.skipIf(os.name == "nt", "test requires bytes path support")
  2521. def test_fspath_protocol_bytes(self):
  2522. bytes_filename = os.fsencode('bytesfile.txt')
  2523. bytes_entry = self.create_file_entry(name=bytes_filename)
  2524. fspath = os.fspath(bytes_entry)
  2525. self.assertIsInstance(fspath, bytes)
  2526. self.assertEqual(fspath,
  2527. os.path.join(os.fsencode(self.path),bytes_filename))
  2528. def test_removed_dir(self):
  2529. path = os.path.join(self.path, 'dir')
  2530. os.mkdir(path)
  2531. entry = self.get_entry('dir')
  2532. os.rmdir(path)
  2533. # On POSIX, is_dir() result depends if scandir() filled d_type or not
  2534. if os.name == 'nt':
  2535. self.assertTrue(entry.is_dir())
  2536. self.assertFalse(entry.is_file())
  2537. self.assertFalse(entry.is_symlink())
  2538. if os.name == 'nt':
  2539. self.assertRaises(FileNotFoundError, entry.inode)
  2540. # don't fail
  2541. entry.stat()
  2542. entry.stat(follow_symlinks=False)
  2543. else:
  2544. self.assertGreater(entry.inode(), 0)
  2545. self.assertRaises(FileNotFoundError, entry.stat)
  2546. self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
  2547. def test_removed_file(self):
  2548. entry = self.create_file_entry()
  2549. os.unlink(entry.path)
  2550. self.assertFalse(entry.is_dir())
  2551. # On POSIX, is_dir() result depends if scandir() filled d_type or not
  2552. if os.name == 'nt':
  2553. self.assertTrue(entry.is_file())
  2554. self.assertFalse(entry.is_symlink())
  2555. if os.name == 'nt':
  2556. self.assertRaises(FileNotFoundError, entry.inode)
  2557. # don't fail
  2558. entry.stat()
  2559. entry.stat(follow_symlinks=False)
  2560. else:
  2561. self.assertGreater(entry.inode(), 0)
  2562. self.assertRaises(FileNotFoundError, entry.stat)
  2563. self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
  2564. def test_broken_symlink(self):
  2565. if not support.can_symlink():
  2566. return self.skipTest('cannot create symbolic link')
  2567. filename = self.create_file("file.txt")
  2568. os.symlink(filename,
  2569. os.path.join(self.path, "symlink.txt"))
  2570. entries = self.get_entries(['file.txt', 'symlink.txt'])
  2571. entry = entries['symlink.txt']
  2572. os.unlink(filename)
  2573. self.assertGreater(entry.inode(), 0)
  2574. self.assertFalse(entry.is_dir())
  2575. self.assertFalse(entry.is_file()) # broken symlink returns False
  2576. self.assertFalse(entry.is_dir(follow_symlinks=False))
  2577. self.assertFalse(entry.is_file(follow_symlinks=False))
  2578. self.assertTrue(entry.is_symlink())
  2579. self.assertRaises(FileNotFoundError, entry.stat)
  2580. # don't fail
  2581. entry.stat(follow_symlinks=False)
  2582. def test_bytes(self):
  2583. if os.name == "nt":
  2584. # On Windows, os.scandir(bytes) must raise an exception
  2585. with bytes_filename_warn(True):
  2586. self.assertRaises(TypeError, os.scandir, b'.')
  2587. return
  2588. self.create_file("file.txt")
  2589. path_bytes = os.fsencode(self.path)
  2590. entries = list(os.scandir(path_bytes))
  2591. self.assertEqual(len(entries), 1, entries)
  2592. entry = entries[0]
  2593. self.assertEqual(entry.name, b'file.txt')
  2594. self.assertEqual(entry.path,
  2595. os.fsencode(os.path.join(self.path, 'file.txt')))
  2596. def test_empty_path(self):
  2597. self.assertRaises(FileNotFoundError, os.scandir, '')
  2598. def test_consume_iterator_twice(self):
  2599. self.create_file("file.txt")
  2600. iterator = os.scandir(self.path)
  2601. entries = list(iterator)
  2602. self.assertEqual(len(entries), 1, entries)
  2603. # check than consuming the iterator twice doesn't raise exception
  2604. entries2 = list(iterator)
  2605. self.assertEqual(len(entries2), 0, entries2)
  2606. def test_bad_path_type(self):
  2607. for obj in [1234, 1.234, {}, []]:
  2608. self.assertRaises(TypeError, os.scandir, obj)
  2609. def test_close(self):
  2610. self.create_file("file.txt")
  2611. self.create_file("file2.txt")
  2612. iterator = os.scandir(self.path)
  2613. next(iterator)
  2614. iterator.close()
  2615. # multiple closes
  2616. iterator.close()
  2617. with self.check_no_resource_warning():
  2618. del iterator
  2619. def test_context_manager(self):
  2620. self.create_file("file.txt")
  2621. self.create_file("file2.txt")
  2622. with os.scandir(self.path) as iterator:
  2623. next(iterator)
  2624. with self.check_no_resource_warning():
  2625. del iterator
  2626. def test_context_manager_close(self):
  2627. self.create_file("file.txt")
  2628. self.create_file("file2.txt")
  2629. with os.scandir(self.path) as iterator:
  2630. next(iterator)
  2631. iterator.close()
  2632. def test_context_manager_exception(self):
  2633. self.create_file("file.txt")
  2634. self.create_file("file2.txt")
  2635. with self.assertRaises(ZeroDivisionError):
  2636. with os.scandir(self.path) as iterator:
  2637. next(iterator)
  2638. 1/0
  2639. with self.check_no_resource_warning():
  2640. del iterator
  2641. def test_resource_warning(self):
  2642. self.create_file("file.txt")
  2643. self.create_file("file2.txt")
  2644. iterator = os.scandir(self.path)
  2645. next(iterator)
  2646. with self.assertWarns(ResourceWarning):
  2647. del iterator
  2648. support.gc_collect()
  2649. # exhausted iterator
  2650. iterator = os.scandir(self.path)
  2651. list(iterator)
  2652. with self.check_no_resource_warning():
  2653. del iterator
  2654. class TestPEP519(unittest.TestCase):
  2655. # Abstracted so it can be overridden to test pure Python implementation
  2656. # if a C version is provided.
  2657. fspath = staticmethod(os.fspath)
  2658. class PathLike:
  2659. def __init__(self, path=''):
  2660. self.path = path
  2661. def __fspath__(self):
  2662. if isinstance(self.path, BaseException):
  2663. raise self.path
  2664. else:
  2665. return self.path
  2666. def test_return_bytes(self):
  2667. for b in b'hello', b'goodbye', b'some/path/and/file':
  2668. self.assertEqual(b, self.fspath(b))
  2669. def test_return_string(self):
  2670. for s in 'hello', 'goodbye', 'some/path/and/file':
  2671. self.assertEqual(s, self.fspath(s))
  2672. def test_fsencode_fsdecode(self):
  2673. for p in "path/like/object", b"path/like/object":
  2674. pathlike = self.PathLike(p)
  2675. self.assertEqual(p, self.fspath(pathlike))
  2676. self.assertEqual(b"path/like/object", os.fsencode(pathlike))
  2677. self.assertEqual("path/like/object", os.fsdecode(pathlike))
  2678. def test_pathlike(self):
  2679. self.assertEqual('#feelthegil', self.fspath(self.PathLike('#feelthegil')))
  2680. self.assertTrue(issubclass(self.PathLike, os.PathLike))
  2681. self.assertTrue(isinstance(self.PathLike(), os.PathLike))
  2682. def test_garbage_in_exception_out(self):
  2683. vapor = type('blah', (), {})
  2684. for o in int, type, os, vapor():
  2685. self.assertRaises(TypeError, self.fspath, o)
  2686. def test_argument_required(self):
  2687. self.assertRaises(TypeError, self.fspath)
  2688. def test_bad_pathlike(self):
  2689. # __fspath__ returns a value other than str or bytes.
  2690. self.assertRaises(TypeError, self.fspath, self.PathLike(42))
  2691. # __fspath__ attribute that is not callable.
  2692. c = type('foo', (), {})
  2693. c.__fspath__ = 1
  2694. self.assertRaises(TypeError, self.fspath, c())
  2695. # __fspath__ raises an exception.
  2696. self.assertRaises(ZeroDivisionError, self.fspath,
  2697. self.PathLike(ZeroDivisionError()))
  2698. # Only test if the C version is provided, otherwise TestPEP519 already tested
  2699. # the pure Python implementation.
  2700. if hasattr(os, "_fspath"):
  2701. class TestPEP519PurePython(TestPEP519):
  2702. """Explicitly test the pure Python implementation of os.fspath()."""
  2703. fspath = staticmethod(os._fspath)
  2704. if __name__ == "__main__":
  2705. unittest.main()