test_file_util.py 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """Tests for distutils.file_util."""
  2. import errno
  3. import os
  4. import unittest.mock as mock
  5. from distutils.errors import DistutilsFileError
  6. from distutils.file_util import copy_file, move_file
  7. import jaraco.path
  8. import pytest
  9. @pytest.fixture(autouse=True)
  10. def stuff(request, tmp_path):
  11. self = request.instance
  12. self.source = tmp_path / 'f1'
  13. self.target = tmp_path / 'f2'
  14. self.target_dir = tmp_path / 'd1'
  15. class TestFileUtil:
  16. def test_move_file_verbosity(self, caplog):
  17. jaraco.path.build({self.source: 'some content'})
  18. move_file(self.source, self.target, verbose=False)
  19. assert not caplog.messages
  20. # back to original state
  21. move_file(self.target, self.source, verbose=False)
  22. move_file(self.source, self.target, verbose=True)
  23. wanted = [f'moving {self.source} -> {self.target}']
  24. assert caplog.messages == wanted
  25. # back to original state
  26. move_file(self.target, self.source, verbose=False)
  27. caplog.clear()
  28. # now the target is a dir
  29. os.mkdir(self.target_dir)
  30. move_file(self.source, self.target_dir, verbose=True)
  31. wanted = [f'moving {self.source} -> {self.target_dir}']
  32. assert caplog.messages == wanted
  33. def test_move_file_exception_unpacking_rename(self):
  34. # see issue 22182
  35. with (
  36. mock.patch("os.rename", side_effect=OSError("wrong", 1)),
  37. pytest.raises(DistutilsFileError),
  38. ):
  39. jaraco.path.build({self.source: 'spam eggs'})
  40. move_file(self.source, self.target, verbose=False)
  41. def test_move_file_exception_unpacking_unlink(self):
  42. # see issue 22182
  43. with (
  44. mock.patch("os.rename", side_effect=OSError(errno.EXDEV, "wrong")),
  45. mock.patch("os.unlink", side_effect=OSError("wrong", 1)),
  46. pytest.raises(DistutilsFileError),
  47. ):
  48. jaraco.path.build({self.source: 'spam eggs'})
  49. move_file(self.source, self.target, verbose=False)
  50. def test_copy_file_hard_link(self):
  51. jaraco.path.build({self.source: 'some content'})
  52. # Check first that copy_file() will not fall back on copying the file
  53. # instead of creating the hard link.
  54. try:
  55. os.link(self.source, self.target)
  56. except OSError as e:
  57. self.skipTest(f'os.link: {e}')
  58. else:
  59. self.target.unlink()
  60. st = os.stat(self.source)
  61. copy_file(self.source, self.target, link='hard')
  62. st2 = os.stat(self.source)
  63. st3 = os.stat(self.target)
  64. assert os.path.samestat(st, st2), (st, st2)
  65. assert os.path.samestat(st2, st3), (st2, st3)
  66. assert self.source.read_text(encoding='utf-8') == 'some content'
  67. def test_copy_file_hard_link_failure(self):
  68. # If hard linking fails, copy_file() falls back on copying file
  69. # (some special filesystems don't support hard linking even under
  70. # Unix, see issue #8876).
  71. jaraco.path.build({self.source: 'some content'})
  72. st = os.stat(self.source)
  73. with mock.patch("os.link", side_effect=OSError(0, "linking unsupported")):
  74. copy_file(self.source, self.target, link='hard')
  75. st2 = os.stat(self.source)
  76. st3 = os.stat(self.target)
  77. assert os.path.samestat(st, st2), (st, st2)
  78. assert not os.path.samestat(st2, st3), (st2, st3)
  79. for fn in (self.source, self.target):
  80. assert fn.read_text(encoding='utf-8') == 'some content'