Coverage for tests/test_file.py: 21%

87 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-12 02:04 -0700

1# This file is part of lsst-resources. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11 

12import os 

13import pathlib 

14import unittest 

15import unittest.mock 

16 

17from lsst.resources import ResourcePath 

18from lsst.resources.tests import GenericReadWriteTestCase, GenericTestCase 

19 

20TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

21 

22 

23class FileTestCase(GenericTestCase, unittest.TestCase): 

24 scheme = "file" 

25 netloc = "localhost" 

26 

27 def test_env_var(self): 

28 """Test that environment variables are expanded.""" 

29 

30 with unittest.mock.patch.dict(os.environ, {"MY_TEST_DIR": "/a/b/c"}): 

31 uri = ResourcePath("${MY_TEST_DIR}/d.txt") 

32 self.assertEqual(uri.path, "/a/b/c/d.txt") 

33 self.assertEqual(uri.scheme, "file") 

34 

35 # This will not expand 

36 uri = ResourcePath("${MY_TEST_DIR}/d.txt", forceAbsolute=False) 

37 self.assertEqual(uri.path, "${MY_TEST_DIR}/d.txt") 

38 self.assertFalse(uri.scheme) 

39 

40 def test_ospath(self): 

41 """File URIs have ospath property.""" 

42 

43 file = ResourcePath(self._make_uri("a/test.txt")) 

44 self.assertEqual(file.ospath, "/a/test.txt") 

45 self.assertEqual(file.ospath, file.path) 

46 

47 # A Schemeless URI can take unquoted files but will be quoted 

48 # when it becomes a file URI. 

49 something = "/a#/???.txt" 

50 file = ResourcePath(something, forceAbsolute=True) 

51 self.assertEqual(file.scheme, "file") 

52 self.assertEqual(file.ospath, something, "From URI: {file}") 

53 self.assertNotIn("???", file.path) 

54 

55 def test_path_lib(self): 

56 """File URIs can be created from pathlib""" 

57 file = ResourcePath(self._make_uri("a/test.txt")) 

58 

59 path_file = pathlib.Path(file.ospath) 

60 from_path = ResourcePath(path_file) 

61 self.assertEqual(from_path.ospath, file.ospath) 

62 

63 def test_schemeless_root(self): 

64 root = ResourcePath(self._make_uri("/root")) 

65 via_root = ResourcePath("b.txt", root=root) 

66 self.assertEqual(via_root.ospath, "/root/b.txt") 

67 

68 

69class FileReadWriteTestCase(GenericReadWriteTestCase, unittest.TestCase): 

70 scheme = "file" 

71 netloc = "localhost" 

72 testdir = TESTDIR 

73 transfer_modes = ("move", "copy", "link", "hardlink", "symlink", "relsymlink") 

74 

75 def test_transfer_identical(self): 

76 """Test overwrite of identical files. 

77 

78 Only relevant for local files. 

79 """ 

80 dir1 = self.tmpdir.join("dir1", forceDirectory=True) 

81 dir1.mkdir() 

82 self.assertTrue(dir1.exists()) 

83 dir2 = self.tmpdir.join("dir2", forceDirectory=True) 

84 # A symlink can't include a trailing slash. 

85 dir2_ospath = dir2.ospath 

86 if dir2_ospath.endswith("/"): 

87 dir2_ospath = dir2_ospath[:-1] 

88 os.symlink(dir1.ospath, dir2_ospath) 

89 

90 # Write a test file. 

91 src_file = dir1.join("test.txt") 

92 content = "0123456" 

93 src_file.write(content.encode()) 

94 

95 # Construct URI to destination that should be identical. 

96 dest_file = dir2.join("test.txt") 

97 self.assertTrue(dest_file.exists()) 

98 self.assertNotEqual(src_file, dest_file) 

99 

100 # Transfer it over itself. 

101 dest_file.transfer_from(src_file, transfer="symlink", overwrite=True) 

102 new_content = dest_file.read().decode() 

103 self.assertEqual(content, new_content) 

104 

105 def test_local_temporary(self): 

106 """Create temporary local file if no prefix specified.""" 

107 with ResourcePath.temporary_uri(suffix=".json") as tmp: 

108 self.assertEqual(tmp.getExtension(), ".json", f"uri: {tmp}") 

109 self.assertTrue(tmp.isabs(), f"uri: {tmp}") 

110 self.assertFalse(tmp.exists(), f"uri: {tmp}") 

111 tmp.write(b"abcd") 

112 self.assertTrue(tmp.exists(), f"uri: {tmp}") 

113 self.assertTrue(tmp.isTemporary) 

114 self.assertTrue(tmp.isLocal) 

115 

116 # If we now ask for a local form of this temporary file 

117 # it should still be temporary and it should not be deleted 

118 # on exit. 

119 with tmp.as_local() as loc: 

120 self.assertEqual(tmp, loc) 

121 self.assertTrue(loc.isTemporary) 

122 self.assertTrue(tmp.exists()) 

123 self.assertFalse(tmp.exists(), f"uri: {tmp}") 

124 

125 def test_transfers_from_local(self): 

126 """Extra tests for local transfers.""" 

127 

128 target = self.tmpdir.join("a/target.txt") 

129 with ResourcePath.temporary_uri() as tmp: 

130 tmp.write(b"") 

131 self.assertTrue(tmp.isTemporary) 

132 

133 # Symlink transfers for temporary resources should 

134 # trigger a debug message. 

135 for transfer in ("symlink", "relsymlink"): 

136 with self.assertLogs("lsst.resources", level="DEBUG") as cm: 

137 target.transfer_from(tmp, transfer) 

138 target.remove() 

139 self.assertIn("Using a symlink for a temporary", "".join(cm.output)) 

140 

141 # Force the target directory to be created. 

142 target.transfer_from(tmp, "move") 

143 self.assertFalse(tmp.exists()) 

144 

145 # Temporary file now gone so transfer should not work. 

146 with self.assertRaises(FileNotFoundError): 

147 target.transfer_from(tmp, "move", overwrite=True) 

148 

149 

150if __name__ == "__main__": 

151 unittest.main()