From 3d082427bc42c2eccbade85e5bc17904844fc27b Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 14:53:11 +0100 Subject: [PATCH 1/7] Refactor background and background tests --- src/dakara_player/background.py | 66 +++++++-- tests/unit/test_background.py | 245 ++++++++++++++++++++++++-------- 2 files changed, 239 insertions(+), 72 deletions(-) diff --git a/src/dakara_player/background.py b/src/dakara_player/background.py index 7a041b3..d887208 100644 --- a/src/dakara_player/background.py +++ b/src/dakara_player/background.py @@ -1,7 +1,7 @@ """Manage background images for media players.""" import logging -from importlib.resources import path +from importlib.resources import as_file, files from pathlib import Path from shutil import copy @@ -97,29 +97,65 @@ def get_background_path(self, background_name, file_name): """ # trying to load from custom directory if self.directory is not None: - file_path = self.directory / file_name - if file_path.exists(): - logger.debug( - "Loading custom %s background file '%s'", background_name, file_name - ) - return Path(copy(file_path, self.destination)) + try: + return self.copy_custom_background(background_name, file_name) + + except FileNotFoundError: + pass # trying to load from package by default try: - with path(self.package, file_name) as file: - logger.debug( - "Loading default %s background file '%s'", - background_name, - file_name, - ) - file_path = Path(file) - return Path(copy(file_path, self.destination)) + return self.copy_default_background(background_name, file_name) except FileNotFoundError as error: raise BackgroundNotFoundError( f"No {background_name} background file found for '{file_name}'" ) from error + def copy_custom_background(self, background_name, file_name): + """Copy a custom background. + + Args: + background_name (str): Name of the background. + file_name (str): Name of the background file. + + Returns: + pathlib.Path: Absolute path to the background file. + + Raises: + FileNotFoundError: If the custom file does not exist (by + `shuti.copy`). + """ + file_path = self.directory / file_name + output_path = Path(copy(file_path, self.destination)) + logger.debug( + "Loading custom %s background file '%s'", background_name, file_name + ) + return output_path + + def copy_default_background(self, background_name, file_name): + """Copy a default background. + + Args: + background_name (str): Name of the background. + file_name (str): Name of the background file. + + Returns: + pathlib.Path: Absolute path to the background file. + + Raises: + FileNotFoundError: If the custom file does not exist (by + `shuti.copy`). + """ + with as_file(files(self.package).joinpath(file_name)) as file_path: + output_path = Path(copy(file_path, self.destination)) + logger.debug( + "Loading default %s background file '%s'", + background_name, + file_name, + ) + return output_path + class BackgroundNotFoundError(DakaraError, FileNotFoundError): """Error raised when a background cannot be found""" diff --git a/tests/unit/test_background.py b/tests/unit/test_background.py index e29332a..e3749d8 100644 --- a/tests/unit/test_background.py +++ b/tests/unit/test_background.py @@ -5,28 +5,19 @@ from dakara_player.background import BackgroundLoader, BackgroundNotFoundError -@patch("dakara_player.background.path", autospec=True) -@patch("dakara_player.background.copy", autospec=True) -@patch.object(Path, "exists", autospec=True) class BackgroundLoaderTestCase(TestCase): """Test the loader for backgrounds.""" - def setUp(self): - # destination - self.destination = Path("/") / "destination" - - def test_load_default(self, mocked_exists, mocked_copy, mocked_path): - """Test to load a default background.""" - mocked_exists.return_value = False - mocked_copy.return_value = Path("/") / "destination" / "idle.png" - mocked_path.return_value.__enter__.return_value = ( - Path("/") / "package" / "idle.png" - ) + @patch.object(BackgroundLoader, "get_background_path", autospec=True) + def test_load(self, mocked_get_background_path): + """Test to load backgrounds.""" + mocked_get_background_path.return_value = Path("destination") / "idle.png" # create the instance loader = BackgroundLoader( - destination=self.destination, + destination=Path("destination"), package="package", + directory=Path("directory"), filenames={"idle": "idle.png"}, ) @@ -39,8 +30,7 @@ def test_load_default(self, mocked_exists, mocked_copy, mocked_path): # assert the backgrounds self.assertDictEqual( - loader.backgrounds, - {"idle": self.destination / "idle.png"}, + loader.backgrounds, {"idle": Path("destination") / "idle.png"} ) # assert logs @@ -48,80 +38,221 @@ def test_load_default(self, mocked_exists, mocked_copy, mocked_path): logger.output, [ "DEBUG:dakara_player.background:Loading backgrounds", - "DEBUG:dakara_player.background:Loading default " - "idle background file 'idle.png'", ], ) - # assert the call of the mocked method - mocked_exists.assert_not_called() - mocked_copy.assert_called_with( - Path("/") / "package" / "idle.png", Path("/") / "destination" + # assert mocks + mocked_get_background_path.assert_called_with(loader, "idle", "idle.png") + + @patch.object(BackgroundLoader, "copy_default_background", autospec=True) + @patch.object(BackgroundLoader, "copy_custom_background", autospec=True) + def test_get_background_path_custom( + self, mocked_copy_custom_background, mocked_copy_default_background + ): + """Test to get a custom background.""" + mocked_copy_custom_background.return_value = Path("destination") / "idle.png" + + # create the instance + loader = BackgroundLoader( + destination=Path("destination"), + package="package", + directory=Path("directory"), ) - mocked_path.assert_called_with("package", "idle.png") - def test_load_custom(self, mocked_exists, mocked_copy, mocked_path): - """Test to load a custom background.""" - mocked_exists.return_value = True - mocked_copy.return_value = Path("/") / "destination" / "idle.png" + # get the backgrounds + path = loader.get_background_path("idle", "idle.png") + + # assert the backgrounds + self.assertEqual(path, Path("destination") / "idle.png") + + # assert the call of the mocked method + mocked_copy_custom_background.assert_called_with(loader, "idle", "idle.png") + mocked_copy_default_background.assert_not_called() + + @patch.object(BackgroundLoader, "copy_default_background", autospec=True) + @patch.object(BackgroundLoader, "copy_custom_background", autospec=True) + def test_get_background_path_default( + self, mocked_copy_custom_background, mocked_copy_default_background + ): + """Test to get a default background.""" + mocked_copy_default_background.return_value = Path("destination") / "idle.png" + + # create the instance + loader = BackgroundLoader(destination=Path("destination"), package="package") + + # get the backgrounds + path = loader.get_background_path("idle", "idle.png") + + # assert the backgrounds + self.assertEqual(path, Path("destination") / "idle.png") + + # assert the call of the mocked method + mocked_copy_custom_background.assert_not_called() + mocked_copy_default_background.assert_called_with(loader, "idle", "idle.png") + + @patch.object(BackgroundLoader, "copy_default_background", autospec=True) + @patch.object(BackgroundLoader, "copy_custom_background", autospec=True) + def test_get_background_path_custom_not_found( + self, mocked_copy_custom_background, mocked_copy_default_background + ): + """Test to get a default background after trying to get a custom one.""" + mocked_copy_custom_background.side_effect = FileNotFoundError() + mocked_copy_default_background.return_value = Path("destination") / "idle.png" # create the instance loader = BackgroundLoader( - destination=self.destination, + destination=Path("destination"), package="package", - directory=Path("/") / "directory", - filenames={"idle": "idle.png"}, + directory=Path("directory"), ) - # load the backgrounds - with self.assertLogs("dakara_player.background", "DEBUG") as logger: - loader.load() + # get the backgrounds + path = loader.get_background_path("idle", "idle.png") # assert the backgrounds - self.assertDictEqual( - loader.backgrounds, {"idle": self.destination / "idle.png"} + self.assertEqual(path, Path("destination") / "idle.png") + + # assert the call of the mocked method + mocked_copy_custom_background.assert_called_with(loader, "idle", "idle.png") + mocked_copy_default_background.assert_called_with(loader, "idle", "idle.png") + + @patch.object(BackgroundLoader, "copy_default_background", autospec=True) + @patch.object(BackgroundLoader, "copy_custom_background", autospec=True) + def test_get_background_path_default_not_found( + self, mocked_copy_custom_background, mocked_copy_default_background + ): + """Test to get a unexisting background.""" + mocked_copy_default_background.side_effect = FileNotFoundError() + + # create the instance + loader = BackgroundLoader( + destination=Path("destination"), + package="package", + ) + + # get the backgrounds + with self.assertRaisesRegex( + BackgroundNotFoundError, "No idle background file found for 'idle.png'" + ): + loader.get_background_path("idle", "idle.png") + + # assert the call of the mocked method + mocked_copy_custom_background.assert_not_called() + mocked_copy_default_background.assert_called_with(loader, "idle", "idle.png") + + @patch("dakara_player.background.copy", autospec=True) + def test_copy_custom_background(self, mocked_copy): + """Test to copy a custom background.""" + mocked_copy.return_value = str(Path("destination") / "idle.png") + + # create the instance + loader = BackgroundLoader( + destination=Path("destination"), + package="package", + directory=Path("directory"), ) + # copy the backgrounds + with self.assertLogs("dakara_player.background", "DEBUG") as logger: + output_path = loader.copy_custom_background("idle", "idle.png") + + # assert the background + self.assertEqual(output_path, Path("destination") / "idle.png") + # assert logs self.assertListEqual( logger.output, [ - "DEBUG:dakara_player.background:Loading backgrounds", "DEBUG:dakara_player.background:Loading custom idle " "background file 'idle.png'", ], ) # assert the call of the mocked method - mocked_exists.assert_called_with(Path("/") / "directory" / "idle.png") mocked_copy.assert_called_with( - Path("/") / "directory" / "idle.png", Path("/") / "destination" + Path("directory") / "idle.png", Path("destination") ) - mocked_path.assert_not_called() - def test_load_error(self, mocked_exists, mocked_copy, mocked_path): - """Test to load one unexisting background.""" - mocked_exists.return_value = False - mocked_path.return_value.__enter__.side_effect = FileNotFoundError + @patch("dakara_player.background.copy", autospec=True) + @patch("dakara_player.background.as_file", autospec=True) + @patch("dakara_player.background.files", autospec=True) + def test_copy_default_background(self, mocked_files, mocked_as_file, mocked_copy): + """Test to copy a default background.""" + mocked_as_file.return_value.__enter__.return_value = ( + Path("package") / "idle.png" + ) + mocked_copy.return_value = str(Path("destination") / "idle.png") # create the instance loader = BackgroundLoader( - destination=self.destination, + destination=Path("destination"), package="package", - directory=Path("/") / "directory", - filenames={"idle": "idle.png"}, ) - # load the backgrounds - with self.assertRaisesRegex( - BackgroundNotFoundError, "No idle background file found for 'idle.png'" - ): - loader.load() + # copy the backgrounds + with self.assertLogs("dakara_player.background", "DEBUG") as logger: + output_path = loader.copy_default_background("idle", "idle.png") - # assert the backgrounds - self.assertDictEqual(loader.backgrounds, {}) + # assert the background + self.assertEqual(output_path, Path("destination") / "idle.png") + + # assert logs + self.assertListEqual( + logger.output, + [ + "DEBUG:dakara_player.background:Loading default " + "idle background file 'idle.png'", + ], + ) # assert the call of the mocked method - mocked_exists.assert_called_with(Path("/") / "directory" / "idle.png") - mocked_copy.assert_not_called() - mocked_path.assert_called_with("package", "idle.png") + mocked_files.assert_called_with("package") + mocked_files.return_value.joinpath.assert_called_with("idle.png") + mocked_copy.assert_called_with( + Path("package") / "idle.png", Path("destination") + ) + + # def test_load_default(self, mocked_exists, mocked_copy, mocked_path): + # """Test to load a default background.""" + # mocked_exists.return_value = False + # mocked_copy.return_value = Path("/") / "destination" / "idle.png" + # mocked_path.return_value.__enter__.return_value = ( + # Path("/") / "package" / "idle.png" + # ) + # + # # create the instance + # loader = BackgroundLoader( + # destination=self.destination, + # package="package", + # filenames={"idle": "idle.png"}, + # ) + # + # # pre assert that there are no backgrounds + # self.assertDictEqual(loader.backgrounds, {}) + # + # # load the backgrounds + # with self.assertLogs("dakara_player.background", "DEBUG") as logger: + # loader.load() + # + # # assert the backgrounds + # self.assertDictEqual( + # loader.backgrounds, + # {"idle": self.destination / "idle.png"}, + # ) + # + # # assert logs + # self.assertListEqual( + # logger.output, + # [ + # "DEBUG:dakara_player.background:Loading backgrounds", + # "DEBUG:dakara_player.background:Loading default " + # "idle background file 'idle.png'", + # ], + # ) + # + # # assert the call of the mocked method + # mocked_exists.assert_not_called() + # mocked_copy.assert_called_with( + # Path("/") / "package" / "idle.png", Path("/") / "destination" + # ) + # mocked_path.assert_called_with("package", "idle.png") From 5ca11c25a8f63bf6a7548dbe4929930f9752c76b Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 15:16:40 +0100 Subject: [PATCH 2/7] Update font --- src/dakara_player/font.py | 14 ++++++++------ tests/unit/test_font.py | 29 +++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/dakara_player/font.py b/src/dakara_player/font.py index 83cf4d7..48a493d 100644 --- a/src/dakara_player/font.py +++ b/src/dakara_player/font.py @@ -4,7 +4,7 @@ import logging import platform from abc import ABC, abstractmethod -from importlib.resources import contents, path +from importlib.resources import as_file, files from pathlib import Path from shutil import copy @@ -76,9 +76,9 @@ def get_font_name_list(self): """ logger.debug("Scanning fonts directory") font_file_name_list = [ - file - for file in contents(self.package) - if Path(file).suffix.lower() in FONT_EXTENSIONS + file.name + for file in files(self.package).iterdir() + if file.is_file() and file.suffix.lower() in FONT_EXTENSIONS ] logger.debug("Found %i font(s) to load", len(font_file_name_list)) @@ -91,8 +91,10 @@ def get_font_path_iterator(self): pathlib.Path: Absolute path to the font, from the package. """ for font_file_name in self.get_font_name_list(): - with path(self.package, font_file_name) as font_file_path: - yield Path(font_file_path) + with as_file( + files(self.package).joinpath(font_file_name) + ) as font_file_path: + yield font_file_path class FontLoaderLinux(FontLoader): diff --git a/tests/unit/test_font.py b/tests/unit/test_font.py index 238976a..e633bf5 100644 --- a/tests/unit/test_font.py +++ b/tests/unit/test_font.py @@ -65,11 +65,16 @@ def test_context_manager(self, mocked_unload): mocked_unload.assert_called_with() - @patch("dakara_player.font.contents", autospec=True) - def test_get_font_name_list(self, mocked_contents): + @patch.object(Path, "is_file", autospec=True) + @patch("dakara_player.font.files", autospec=True) + def test_get_font_name_list(self, mocked_files, mocked_is_file): """Test to get list of font names.""" # mock system calls - mocked_contents.return_value = [self.font_name, "__init__.py"] + mocked_files.return_value.iterdir.return_value = [ + Path("dir") / self.font_name, + Path("dir") / "__init__.py", + ] + mocked_is_file.return_value = True font_loader = self.get_font_loader() @@ -89,15 +94,18 @@ def test_get_font_name_list(self, mocked_contents): ], ) - # call assertions - mocked_contents.assert_called_once_with("package") + # assert mock + mocked_files.assert_called_once_with("package") - @patch("dakara_player.font.path") + @patch("dakara_player.font.as_file") + @patch("dakara_player.font.files") @patch.object(FontLoaderLinux, "get_font_name_list", autospec=True) - def test_get_font_path_iterator(self, mocked_get_font_name_list, mocked_path): + def test_get_font_path_iterator( + self, mocked_get_font_name_list, mocked_files, mocked_as_file + ): """Test to get iterator of font paths.""" mocked_get_font_name_list.return_value = self.font_name_list - mocked_path.return_value.__enter__.return_value = ( + mocked_as_file.return_value.__enter__.return_value = ( self.directory / self.font_name ) @@ -106,8 +114,13 @@ def test_get_font_path_iterator(self, mocked_get_font_name_list, mocked_path): # call the method font_file_path_list = list(font_loader.get_font_path_iterator()) + # assert the result self.assertListEqual(font_file_path_list, [self.font_path]) + # assert mock + mocked_files.assert_called_once_with("package") + mocked_files.return_value.joinpath.assert_called_once_with(self.font_name) + @skipUnless(platform.system() == "Linux", "Can be tested on Linux only") class FontLoaderLinuxTestCase(FontLoaderTestCase): From beb3cb43cc35ce504e26015b5208dcc8b9fa219f Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 15:30:41 +0100 Subject: [PATCH 3/7] Update user resources --- src/dakara_player/user_resources.py | 13 ++-- tests/unit/test_user_resources.py | 92 +++++++++++++---------------- 2 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/dakara_player/user_resources.py b/src/dakara_player/user_resources.py index 3ab2f7d..0ab77da 100644 --- a/src/dakara_player/user_resources.py +++ b/src/dakara_player/user_resources.py @@ -2,7 +2,7 @@ import logging from distutils.util import strtobool -from importlib.resources import contents, path +from importlib.resources import files from shutil import copy from dakara_base.directory import directories @@ -10,11 +10,11 @@ logger = logging.getLogger(__name__) -def copy_resource(resource, destination, force): +def copy_resource(package, destination, force): """Copy the content of one resource directory. Args: - resource (str): Resource to copy. + package (str): Package of resources to copy. destination (pathlib.Path): Directory where to copy the resource. force (bool): If the destination exists and this flag is set to `True`, overwrite the destination. @@ -36,13 +36,12 @@ def copy_resource(resource, destination, force): destination.mkdir(parents=True, exist_ok=True) - for file_name in contents(resource): + for resource in files(package).iterdir(): # ignore Python files - if file_name.startswith("__"): + if resource.name.startswith("__"): continue - with path(resource, file_name) as file: - copy(file, destination) + copy(resource, destination) def create_resource_files(force=False): diff --git a/tests/unit/test_user_resources.py b/tests/unit/test_user_resources.py index 4161640..2750245 100644 --- a/tests/unit/test_user_resources.py +++ b/tests/unit/test_user_resources.py @@ -11,24 +11,22 @@ class CopyResourceTestCase(TestCase): """Test the copy_resource function.""" @patch("dakara_player.user_resources.copy", autospec=True) - @patch("dakara_player.user_resources.path", autospec=True) - @patch("dakara_player.user_resources.contents", autospec=True) + @patch("dakara_player.user_resources.files", autospec=True) @patch.object(Path, "mkdir", autospec=True) @patch.object(Path, "exists", autospec=True) def test_copy( self, mocked_exists, mocked_mkdir, - mocked_contents, - mocked_path, + mocked_files, mocked_copy, ): """Test to copy files in a non existing directory.""" mocked_exists.return_value = False - mocked_contents.return_value = ["file1.ext", "file2.ext", "__init__.py"] - mocked_path.return_value.__enter__.side_effect = [ - Path("path/to/file1.ext"), - Path("path/to/file2.ext"), + mocked_files.return_value.iterdir.return_value = [ + Path("package/resources/file1.ext"), + Path("package/resources/file2.ext"), + Path("package/resources/__init__.py"), ] user_resources.copy_resource("package.resources", Path("destination"), False) @@ -37,35 +35,33 @@ def test_copy( mocked_mkdir.assert_called_with( Path("destination"), parents=True, exist_ok=True ) - mocked_contents.assert_called_with("package.resources") + mocked_files.assert_called_with("package.resources") mocked_copy.assert_has_calls( [ - call(Path("path/to/file1.ext"), Path("destination")), - call(Path("path/to/file2.ext"), Path("destination")), + call(Path("package/resources/file1.ext"), Path("destination")), + call(Path("package/resources/file2.ext"), Path("destination")), ] ) @patch("dakara_player.user_resources.input") @patch("dakara_player.user_resources.copy", autospec=True) - @patch("dakara_player.user_resources.path", autospec=True) - @patch("dakara_player.user_resources.contents", autospec=True) + @patch("dakara_player.user_resources.files", autospec=True) @patch.object(Path, "mkdir", autospec=True) @patch.object(Path, "exists", autospec=True) def test_copy_existing_abort( self, mocked_exists, mocked_mkdir, - mocked_contents, - mocked_path, + mocked_files, mocked_copy, mocked_input, ): """Test to copy files in an existing directory and abort.""" mocked_exists.return_value = True - mocked_contents.return_value = ["file1.ext", "file2.ext", "__init__.py"] - mocked_path.return_value.__enter__.side_effect = [ - Path("path/to/file1.ext"), - Path("path/to/file2.ext"), + mocked_files.return_value.iterdir.return_value = [ + Path("package/resources/file1.ext"), + Path("package/resources/file2.ext"), + Path("package/resources/__init__.py"), ] mocked_input.return_value = "no" @@ -73,30 +69,28 @@ def test_copy_existing_abort( mocked_exists.assert_called_with(Path("destination")) mocked_mkdir.assert_not_called() - mocked_contents.assert_not_called() + mocked_files.assert_not_called() mocked_copy.assert_not_called() @patch("dakara_player.user_resources.input") @patch("dakara_player.user_resources.copy", autospec=True) - @patch("dakara_player.user_resources.path", autospec=True) - @patch("dakara_player.user_resources.contents", autospec=True) + @patch("dakara_player.user_resources.files", autospec=True) @patch.object(Path, "mkdir", autospec=True) @patch.object(Path, "exists", autospec=True) def test_copy_existing_abort_invalid( self, mocked_exists, mocked_mkdir, - mocked_contents, - mocked_path, + mocked_files, mocked_copy, mocked_input, ): """Test to copy files in an existing directory and abort on invalid input.""" mocked_exists.return_value = True - mocked_contents.return_value = ["file1.ext", "file2.ext", "__init__.py"] - mocked_path.return_value.__enter__.side_effect = [ - Path("path/to/file1.ext"), - Path("path/to/file2.ext"), + mocked_files.return_value.iterdir.return_value = [ + Path("package/resources/file1.ext"), + Path("package/resources/file2.ext"), + Path("package/resources/__init__.py"), ] mocked_input.return_value = "aaa" @@ -104,30 +98,28 @@ def test_copy_existing_abort_invalid( mocked_exists.assert_called_with(Path("destination")) mocked_mkdir.assert_not_called() - mocked_contents.assert_not_called() + mocked_files.assert_not_called() mocked_copy.assert_not_called() @patch("dakara_player.user_resources.input") @patch("dakara_player.user_resources.copy", autospec=True) - @patch("dakara_player.user_resources.path", autospec=True) - @patch("dakara_player.user_resources.contents", autospec=True) + @patch("dakara_player.user_resources.files", autospec=True) @patch.object(Path, "mkdir", autospec=True) @patch.object(Path, "exists", autospec=True) def test_copy_existing_overwrite( self, mocked_exists, mocked_mkdir, - mocked_contents, - mocked_path, + mocked_files, mocked_copy, mocked_input, ): """Test to copy files in an existing directory and overwrite.""" mocked_exists.return_value = True - mocked_contents.return_value = ["file1.ext", "file2.ext", "__init__.py"] - mocked_path.return_value.__enter__.side_effect = [ - Path("path/to/file1.ext"), - Path("path/to/file2.ext"), + mocked_files.return_value.iterdir.return_value = [ + Path("package/resources/file1.ext"), + Path("package/resources/file2.ext"), + Path("package/resources/__init__.py"), ] mocked_input.return_value = "yes" @@ -137,35 +129,33 @@ def test_copy_existing_overwrite( mocked_mkdir.assert_called_with( Path("destination"), parents=True, exist_ok=True ) - mocked_contents.assert_called_with("package.resources") + mocked_files.assert_called_with("package.resources") mocked_copy.assert_has_calls( [ - call(Path("path/to/file1.ext"), Path("destination")), - call(Path("path/to/file2.ext"), Path("destination")), + call(Path("package/resources/file1.ext"), Path("destination")), + call(Path("package/resources/file2.ext"), Path("destination")), ] ) @patch("dakara_player.user_resources.input") @patch("dakara_player.user_resources.copy", autospec=True) - @patch("dakara_player.user_resources.path", autospec=True) - @patch("dakara_player.user_resources.contents", autospec=True) + @patch("dakara_player.user_resources.files", autospec=True) @patch.object(Path, "mkdir", autospec=True) @patch.object(Path, "exists", autospec=True) def test_copy_existing_force( self, mocked_exists, mocked_mkdir, - mocked_contents, - mocked_path, + mocked_files, mocked_copy, mocked_input, ): """Test to force copy files in an existing directory.""" mocked_exists.return_value = True - mocked_contents.return_value = ["file1.ext", "file2.ext", "__init__.py"] - mocked_path.return_value.__enter__.side_effect = [ - Path("path/to/file1.ext"), - Path("path/to/file2.ext"), + mocked_files.return_value.iterdir.return_value = [ + Path("package/resources/file1.ext"), + Path("package/resources/file2.ext"), + Path("package/resources/__init__.py"), ] user_resources.copy_resource("package.resources", Path("destination"), True) @@ -175,11 +165,11 @@ def test_copy_existing_force( mocked_mkdir.assert_called_with( Path("destination"), parents=True, exist_ok=True ) - mocked_contents.assert_called_with("package.resources") + mocked_files.assert_called_with("package.resources") mocked_copy.assert_has_calls( [ - call(Path("path/to/file1.ext"), Path("destination")), - call(Path("path/to/file2.ext"), Path("destination")), + call(Path("package/resources/file1.ext"), Path("destination")), + call(Path("package/resources/file2.ext"), Path("destination")), ] ) From 0a8cfabc9b96f71d66d5ac0dc291527aed619f1a Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 15:32:45 +0100 Subject: [PATCH 4/7] Use dakara_base.utils.strtobool instead of distutils.util.strtobool --- src/dakara_player/user_resources.py | 16 ++++++---------- tests/unit/test_user_resources.py | 29 ----------------------------- 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/dakara_player/user_resources.py b/src/dakara_player/user_resources.py index 0ab77da..74fb66b 100644 --- a/src/dakara_player/user_resources.py +++ b/src/dakara_player/user_resources.py @@ -1,11 +1,11 @@ """Manage the user resource directory and files.""" import logging -from distutils.util import strtobool from importlib.resources import files from shutil import copy from dakara_base.directory import directories +from dakara_base.utils import strtobool logger = logging.getLogger(__name__) @@ -20,16 +20,12 @@ def copy_resource(package, destination, force): overwrite the destination. """ if not force and destination.exists(): - try: - result = strtobool( - input( - f"Directory {destination} already exists, " - "overwrite it with its content? [y/N] " - ) + result = strtobool( + input( + f"Directory {destination} already exists, " + "overwrite it with its content? [y/N] " ) - - except ValueError: - result = False + ) if not result: return diff --git a/tests/unit/test_user_resources.py b/tests/unit/test_user_resources.py index 2750245..2ebfb83 100644 --- a/tests/unit/test_user_resources.py +++ b/tests/unit/test_user_resources.py @@ -72,35 +72,6 @@ def test_copy_existing_abort( mocked_files.assert_not_called() mocked_copy.assert_not_called() - @patch("dakara_player.user_resources.input") - @patch("dakara_player.user_resources.copy", autospec=True) - @patch("dakara_player.user_resources.files", autospec=True) - @patch.object(Path, "mkdir", autospec=True) - @patch.object(Path, "exists", autospec=True) - def test_copy_existing_abort_invalid( - self, - mocked_exists, - mocked_mkdir, - mocked_files, - mocked_copy, - mocked_input, - ): - """Test to copy files in an existing directory and abort on invalid input.""" - mocked_exists.return_value = True - mocked_files.return_value.iterdir.return_value = [ - Path("package/resources/file1.ext"), - Path("package/resources/file2.ext"), - Path("package/resources/__init__.py"), - ] - mocked_input.return_value = "aaa" - - user_resources.copy_resource("package.resources", Path("destination"), False) - - mocked_exists.assert_called_with(Path("destination")) - mocked_mkdir.assert_not_called() - mocked_files.assert_not_called() - mocked_copy.assert_not_called() - @patch("dakara_player.user_resources.input") @patch("dakara_player.user_resources.copy", autospec=True) @patch("dakara_player.user_resources.files", autospec=True) From 90444039610448e79358acb242c09b940c75adce Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 15:34:03 +0100 Subject: [PATCH 5/7] Update other parts of the project --- src/dakara_player/text.py | 4 ++-- tests/integration/base.py | 19 +++++++------------ tests/unit/test_audio.py | 8 ++++---- tests/unit/test_text.py | 19 +++++++++---------- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/dakara_player/text.py b/src/dakara_player/text.py index d07bd13..9db3310 100644 --- a/src/dakara_player/text.py +++ b/src/dakara_player/text.py @@ -2,7 +2,7 @@ import json import logging -from importlib.resources import path +from importlib.resources import as_file, files from pathlib import Path from dakara_base.exceptions import DakaraError @@ -88,7 +88,7 @@ def load(self): def load_icon_map(self): """Load the icon map.""" - with path("dakara_player.resources", ICON_MAP_FILE) as file: + with as_file(files("dakara_player.resources").joinpath(ICON_MAP_FILE)) as file: self.icon_map = json.loads(file.read_text()) def load_templates(self): diff --git a/tests/integration/base.py b/tests/integration/base.py index 3bfea05..d89424b 100644 --- a/tests/integration/base.py +++ b/tests/integration/base.py @@ -1,3 +1,4 @@ +from importlib.resources import as_file, files from pathlib import Path from queue import Empty from shutil import copy @@ -5,12 +6,6 @@ from time import sleep from unittest import TestCase -try: - from importlib.resources import path - -except ImportError: - from importlib_resources import path - class TestCasePoller(TestCase): """Test class that can poll the state of tested player.""" @@ -94,24 +89,24 @@ def setUp(self): self.kara_folder_path = Path(self.kara_folder.name).resolve() # create subtitle - with path("tests.resources", "song1.ass") as file: + with as_file(files("tests.resources").joinpath("song1.ass")) as file: self.subtitle1_path = Path(copy(file, self.kara_folder_path)) - with path("tests.resources", "song2.ass") as file: + with as_file(files("tests.resources").joinpath("song2.ass")) as file: self.subtitle2_path = Path(copy(file, self.kara_folder_path)) # create song - with path("tests.resources", "song1.mkv") as file: + with as_file(files("tests.resources").joinpath("song1.mkv")) as file: self.song1_path = Path(copy(file, self.kara_folder_path)) - with path("tests.resources", "song2.mkv") as file: + with as_file(files("tests.resources").joinpath("song2.mkv")) as file: self.song2_path = Path(copy(file, self.kara_folder_path)) - with path("tests.resources", "song3.avi") as file: + with as_file(files("tests.resources").joinpath("song3.avi")) as file: self.song3_path = Path(copy(file, self.kara_folder_path)) # create audio - with path("tests.resources", "song2.mp3") as file: + with as_file(files("tests.resources").joinpath("song2.mp3")) as file: self.audio2_path = Path(copy(file, self.kara_folder_path)) # create playlist entry diff --git a/tests/unit/test_audio.py b/tests/unit/test_audio.py index a901622..f757f53 100644 --- a/tests/unit/test_audio.py +++ b/tests/unit/test_audio.py @@ -1,4 +1,4 @@ -from importlib.resources import path +from importlib.resources import as_file, files from pathlib import Path from unittest import TestCase from unittest.mock import patch @@ -9,17 +9,17 @@ class IsAudioFileTestCase(TestCase): def test_mp3(self): """Test to detect a MP3 file.""" - with path("tests.resources", "song2.mp3") as file: + with as_file(files("tests.resources").joinpath("song2.mp3")) as file: self.assertTrue(is_audio_file(file)) def test_ass(self): """Test to not detect an ASS file.""" - with path("tests.resources", "song2.ass") as file: + with as_file(files("tests.resources").joinpath("song2.ass")) as file: self.assertFalse(is_audio_file(file)) def test_mkv(self): """Test to not detect a MKV file.""" - with path("tests.resources", "song2.mkv") as file: + with as_file(files("tests.resources").joinpath("song2.mkv")) as file: self.assertFalse(is_audio_file(file)) diff --git a/tests/unit/test_text.py b/tests/unit/test_text.py index c218af0..86f8193 100644 --- a/tests/unit/test_text.py +++ b/tests/unit/test_text.py @@ -1,3 +1,4 @@ +from importlib.resources import as_file, files from pathlib import Path from pathlib import Path as Path_pathlib from shutil import copy @@ -5,12 +6,6 @@ from unittest import TestCase from unittest.mock import MagicMock, patch -try: - from importlib.resources import path - -except ImportError: - from importlib_resources import path - from dakara_player.text import ( TemplateNotFoundError, TextGenerator, @@ -287,10 +282,14 @@ def test_load_templates_custom(self): temp = Path(temp_str) # prepare directory - with path("dakara_player.resources.templates", "idle.ass") as file: + with as_file( + files("dakara_player.resources.templates").joinpath("idle.ass") + ) as file: copy(file, temp) - with path("dakara_player.resources.templates", "transition.ass") as file: + with as_file( + files("dakara_player.resources.templates").joinpath("transition.ass") + ) as file: copy(file, temp) # create object @@ -314,7 +313,7 @@ def test_get_idle_text(self): result = self.text_generator.get_text("idle", self.idle_info) # check file content - with path("tests.resources", "idle.ass") as file: + with as_file(files("tests.resources").joinpath("idle.ass")) as file: idle_text_content = file.read_text(encoding="utf8") self.assertEqual(idle_text_content.rstrip(), result.rstrip()) @@ -326,7 +325,7 @@ def test_get_transition_text(self): ) # check file content - with path("tests.resources", "transition.ass") as file: + with as_file(files("tests.resources").joinpath("transition.ass")) as file: transition_text_content = file.read_text(encoding="utf8") self.assertEqual(transition_text_content.rstrip(), result.rstrip()) From fe739b9a98f3512c424b36bad3594b84801c2108 Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 15:40:25 +0100 Subject: [PATCH 6/7] [skip ci] Remove commented code --- tests/unit/test_background.py | 45 ----------------------------------- 1 file changed, 45 deletions(-) diff --git a/tests/unit/test_background.py b/tests/unit/test_background.py index e3749d8..490a7b2 100644 --- a/tests/unit/test_background.py +++ b/tests/unit/test_background.py @@ -211,48 +211,3 @@ def test_copy_default_background(self, mocked_files, mocked_as_file, mocked_copy mocked_copy.assert_called_with( Path("package") / "idle.png", Path("destination") ) - - # def test_load_default(self, mocked_exists, mocked_copy, mocked_path): - # """Test to load a default background.""" - # mocked_exists.return_value = False - # mocked_copy.return_value = Path("/") / "destination" / "idle.png" - # mocked_path.return_value.__enter__.return_value = ( - # Path("/") / "package" / "idle.png" - # ) - # - # # create the instance - # loader = BackgroundLoader( - # destination=self.destination, - # package="package", - # filenames={"idle": "idle.png"}, - # ) - # - # # pre assert that there are no backgrounds - # self.assertDictEqual(loader.backgrounds, {}) - # - # # load the backgrounds - # with self.assertLogs("dakara_player.background", "DEBUG") as logger: - # loader.load() - # - # # assert the backgrounds - # self.assertDictEqual( - # loader.backgrounds, - # {"idle": self.destination / "idle.png"}, - # ) - # - # # assert logs - # self.assertListEqual( - # logger.output, - # [ - # "DEBUG:dakara_player.background:Loading backgrounds", - # "DEBUG:dakara_player.background:Loading default " - # "idle background file 'idle.png'", - # ], - # ) - # - # # assert the call of the mocked method - # mocked_exists.assert_not_called() - # mocked_copy.assert_called_with( - # Path("/") / "package" / "idle.png", Path("/") / "destination" - # ) - # mocked_path.assert_called_with("package", "idle.png") From 0e6d682dca893f7387ebbbc13c7b69b9289b6c28 Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 16 Feb 2025 15:43:35 +0100 Subject: [PATCH 7/7] Add missing autospecs in test_font --- tests/unit/test_font.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/unit/test_font.py b/tests/unit/test_font.py index e633bf5..6030130 100644 --- a/tests/unit/test_font.py +++ b/tests/unit/test_font.py @@ -57,13 +57,13 @@ def get_font_loader(self): with self.assertLogs("dakara_player.font", "DEBUG"): return FontLoaderLinux("package") - @patch.object(FontLoaderLinux, "unload") + @patch.object(FontLoaderLinux, "unload", autospec=True) def test_context_manager(self, mocked_unload): """Test the font loader context manager.""" - with FontLoaderLinux("package"): + with FontLoaderLinux("package") as loader: pass - mocked_unload.assert_called_with() + mocked_unload.assert_called_with(loader) @patch.object(Path, "is_file", autospec=True) @patch("dakara_player.font.files", autospec=True) @@ -97,8 +97,8 @@ def test_get_font_name_list(self, mocked_files, mocked_is_file): # assert mock mocked_files.assert_called_once_with("package") - @patch("dakara_player.font.as_file") - @patch("dakara_player.font.files") + @patch("dakara_player.font.as_file", autospec=True) + @patch("dakara_player.font.files", autospec=True) @patch.object(FontLoaderLinux, "get_font_name_list", autospec=True) def test_get_font_path_iterator( self, mocked_get_font_name_list, mocked_files, mocked_as_file @@ -505,7 +505,7 @@ def test_load_font_error(self, mocked_ctypes): ) @patch("dakara_player.font.ctypes") - @patch.object(FontLoaderWindows, "unload_font") + @patch.object(FontLoaderWindows, "unload_font", autospec=True) def test_unload(self, mocked_unload_font, mocked_ctypes): """Test to unload fonts.""" font_loader = self.get_font_loader() @@ -517,7 +517,9 @@ def test_unload(self, mocked_unload_font, mocked_ctypes): font_loader.unload() # assert the call - mocked_unload_font.assert_has_calls([call("font1"), call("font2")]) + mocked_unload_font.assert_has_calls( + [call(font_loader, "font1"), call(font_loader, "font2")] + ) @patch("dakara_player.font.ctypes") def test_unload_font(self, mocked_ctypes):