Coverage for tests/test_file.py: 22%

91 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-03-09 03:06 -0800

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 with self.assertRaises(ValueError): 

69 # Scheme-less URIs are not allowed to support non-file roots 

70 # at the present time. This may change in the future to become 

71 # equivalent to ResourcePath.join() 

72 ResourcePath("a/b.txt", root=ResourcePath("s3://bucket/a/b/")) 

73 

74 

75class FileReadWriteTestCase(GenericReadWriteTestCase, unittest.TestCase): 

76 scheme = "file" 

77 netloc = "localhost" 

78 testdir = TESTDIR 

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

80 

81 def test_transfer_identical(self): 

82 """Test overwrite of identical files. 

83 

84 Only relevant for local files. 

85 """ 

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

87 dir1.mkdir() 

88 self.assertTrue(dir1.exists()) 

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

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

91 dir2_ospath = dir2.ospath 

92 if dir2_ospath.endswith("/"): 

93 dir2_ospath = dir2_ospath[:-1] 

94 os.symlink(dir1.ospath, dir2_ospath) 

95 

96 # Write a test file. 

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

98 content = "0123456" 

99 src_file.write(content.encode()) 

100 

101 # Construct URI to destination that should be identical. 

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

103 self.assertTrue(dest_file.exists()) 

104 self.assertNotEqual(src_file, dest_file) 

105 

106 # Transfer it over itself. 

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

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

109 self.assertEqual(content, new_content) 

110 

111 def test_local_temporary(self): 

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

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

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

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

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

117 tmp.write(b"abcd") 

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

119 self.assertTrue(tmp.isTemporary) 

120 self.assertTrue(tmp.isLocal) 

121 

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

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

124 # on exit. 

125 with tmp.as_local() as loc: 

126 self.assertEqual(tmp, loc) 

127 self.assertTrue(loc.isTemporary) 

128 self.assertTrue(tmp.exists()) 

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

130 

131 def test_transfers_from_local(self): 

132 """Extra tests for local transfers.""" 

133 

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

135 with ResourcePath.temporary_uri() as tmp: 

136 tmp.write(b"") 

137 self.assertTrue(tmp.isTemporary) 

138 

139 # Symlink transfers for temporary resources should 

140 # trigger a debug message. 

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

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

143 target.transfer_from(tmp, transfer) 

144 target.remove() 

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

146 

147 # Force the target directory to be created. 

148 target.transfer_from(tmp, "move") 

149 self.assertFalse(tmp.exists()) 

150 

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

152 with self.assertRaises(FileNotFoundError): 

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

154 

155 

156if __name__ == "__main__": 156 ↛ 157line 156 didn't jump to line 157, because the condition on line 156 was never true

157 unittest.main()