From cd234d416a74e239dac08534a9bd98e3a7cd7890 Mon Sep 17 00:00:00 2001 From: Olivier Gayot Date: Fri, 19 Jan 2024 20:09:25 +0100 Subject: [PATCH] mounter: support pathlib.Path in components Instead of supporting only string components, mount.p() now supports strings, pathlib.Path()s, or a combination of both. Signed-off-by: Olivier Gayot --- subiquity/server/mounter.py | 6 +++--- subiquity/server/tests/test_mounter.py | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/subiquity/server/mounter.py b/subiquity/server/mounter.py index f12f020d..73cf8255 100644 --- a/subiquity/server/mounter.py +++ b/subiquity/server/mounter.py @@ -56,11 +56,11 @@ class AbsolutePathError(Exception): class _MountBase: - def p(self, *args: str) -> str: + def p(self, *args: Union[str, Path]) -> Path: for a in args: - if a.startswith("/"): + if Path(a).is_absolute(): raise AbsolutePathError("no absolute paths here please") - return os.path.join(self.mountpoint, *args) + return str(Path(self.mountpoint).joinpath(*args)) def write(self, path, content): with open(self.p(path), "w") as fp: diff --git a/subiquity/server/tests/test_mounter.py b/subiquity/server/tests/test_mounter.py index e3945708..f38f8212 100644 --- a/subiquity/server/tests/test_mounter.py +++ b/subiquity/server/tests/test_mounter.py @@ -14,7 +14,7 @@ # along with this program. If not, see . import os -import pathlib +from pathlib import Path from unittest.mock import AsyncMock, Mock, call, patch from subiquity.server.mounter import ( @@ -40,9 +40,15 @@ class Test_MountBase(SubiTestCase): self.assertEqual("/target/d1", mnt.p("d1")) self.assertEqual("/target/d1/d2/d3/d4", mnt.p("d1", "d2/d3", "d4")) + # Mix of strings and paths should produce the same result. + self.assertEqual(mnt.p("d1", "d2/d3"), mnt.p("d1", Path("d2/d3"))) + self.assertEqual(mnt.p("d1", "d2/d3"), mnt.p(Path("d1"), "d2/d3")) + def test_p__absolute(self): with self.assertRaises(AbsolutePathError): self.mountbase.p("a", "/b") + with self.assertRaises(AbsolutePathError): + self.mountbase.p("a", pathlib.Path("/b")) class TestMounter(SubiTestCase): @@ -134,7 +140,7 @@ class TestMounter(SubiTestCase): # When we are bind mounting a directory, the destination should be # created as a directory. src = self.tmp_dir() - dst = pathlib.Path(self.tmp_dir()) / "dst" + dst = Path(self.tmp_dir()) / "dst" self.app.command_runner = AsyncMock() await mounter.bind_mount_tree(src, dst) @@ -144,9 +150,9 @@ class TestMounter(SubiTestCase): mounter = Mounter(self.app) # When we are bind mounting a file, the destination should be created # as a file. - src = pathlib.Path(self.tmp_dir()) / "src" + src = Path(self.tmp_dir()) / "src" src.touch() - dst = pathlib.Path(self.tmp_dir()) / "dst" + dst = Path(self.tmp_dir()) / "dst" self.app.command_runner = AsyncMock() await mounter.bind_mount_tree(src, dst) @@ -156,9 +162,9 @@ class TestMounter(SubiTestCase): mounter = Mounter(self.app) # When we are mounting a device, the destination should be created # as a directory. - src = pathlib.Path(self.tmp_dir()) / "src" + src = Path(self.tmp_dir()) / "src" src.touch() - dst = pathlib.Path(self.tmp_dir()) / "dst" + dst = Path(self.tmp_dir()) / "dst" self.app.command_runner = AsyncMock() await mounter.mount(src, dst)