Coverage for tests/test_file.py: 21%
87 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-09 02:04 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-09 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.
12import os
13import pathlib
14import unittest
15import unittest.mock
17from lsst.resources import ResourcePath
18from lsst.resources.tests import GenericReadWriteTestCase, GenericTestCase
20TESTDIR = os.path.abspath(os.path.dirname(__file__))
23class FileTestCase(GenericTestCase, unittest.TestCase):
24 scheme = "file"
25 netloc = "localhost"
27 def test_env_var(self):
28 """Test that environment variables are expanded."""
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")
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)
40 def test_ospath(self):
41 """File URIs have ospath property."""
43 file = ResourcePath(self._make_uri("a/test.txt"))
44 self.assertEqual(file.ospath, "/a/test.txt")
45 self.assertEqual(file.ospath, file.path)
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)
55 def test_path_lib(self):
56 """File URIs can be created from pathlib"""
57 file = ResourcePath(self._make_uri("a/test.txt"))
59 path_file = pathlib.Path(file.ospath)
60 from_path = ResourcePath(path_file)
61 self.assertEqual(from_path.ospath, file.ospath)
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")
69class FileReadWriteTestCase(GenericReadWriteTestCase, unittest.TestCase):
70 scheme = "file"
71 netloc = "localhost"
72 testdir = TESTDIR
73 transfer_modes = ("move", "copy", "link", "hardlink", "symlink", "relsymlink")
75 def test_transfer_identical(self):
76 """Test overwrite of identical files.
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)
90 # Write a test file.
91 src_file = dir1.join("test.txt")
92 content = "0123456"
93 src_file.write(content.encode())
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)
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)
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)
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}")
125 def test_transfers_from_local(self):
126 """Extra tests for local transfers."""
128 target = self.tmpdir.join("a/target.txt")
129 with ResourcePath.temporary_uri() as tmp:
130 tmp.write(b"")
131 self.assertTrue(tmp.isTemporary)
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))
141 # Force the target directory to be created.
142 target.transfer_from(tmp, "move")
143 self.assertFalse(tmp.exists())
145 # Temporary file now gone so transfer should not work.
146 with self.assertRaises(FileNotFoundError):
147 target.transfer_from(tmp, "move", overwrite=True)
150if __name__ == "__main__":
151 unittest.main()