Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions src/dakara_base/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,16 @@
"""

import logging
import shutil
from collections import UserDict
from importlib.resources import as_file, files
from shutil import copyfile

import coloredlogs
import progressbar
import yaml
import yaml.parser
from environs import Env, EnvError

try:
from importlib.resources import path

except ImportError:
from importlib_resources import path

from dakara_base.directory import directories
from dakara_base.exceptions import DakaraError
from dakara_base.utils import strtobool
Expand Down Expand Up @@ -304,7 +299,7 @@ def create_config_file(resource, filename, force=False):
force (bool): If True, config file in user directory is overwritten if
it existed already. Otherwise, prompt the user.
"""
with path(resource, filename) as origin:
with as_file(files(resource).joinpath(filename)) as origin:
# get the file
destination = directories.user_config_path / filename

Expand All @@ -321,8 +316,8 @@ def create_config_file(resource, filename, force=False):
return

# copy file
shutil.copyfile(origin, destination)
logger.info("Config created in '{}'".format(destination))
copyfile(origin, destination)
logger.info("Config created in '%s'", destination)


class ConfigError(DakaraError):
Expand Down
83 changes: 32 additions & 51 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import os
from unittest import TestCase
from unittest.mock import ANY, MagicMock, PropertyMock, patch

try:
from importlib.resources import path

except ImportError:
from importlib_resources import path

from importlib.resources import as_file, files
from pathlib import Path
from unittest import TestCase
from unittest.mock import PropertyMock, patch

from environs import Env
from platformdirs import PlatformDirs
Expand Down Expand Up @@ -165,7 +159,7 @@ def test_load_file_success(self):

# call the method
with self.assertLogs("dakara_base.config", "DEBUG") as logger:
with path("tests.resources", "config.yaml") as file:
with as_file(files("tests.resources").joinpath("config.yaml")) as file:
config.load_file(Path(file))

# assert the result
Expand Down Expand Up @@ -196,7 +190,7 @@ def test_load_file_fail_parser_error(self, mocked_safe_load):

# call the method
with self.assertLogs("dakara_base.config", "DEBUG"):
with path("tests.resources", "config.yaml") as file:
with as_file(files("tests.resources").joinpath("config.yaml")) as file:
with self.assertRaisesRegex(
ConfigParseError, "Unable to parse config file"
):
Expand All @@ -207,7 +201,7 @@ def test_config_env(self):
config = Config("DAKARA")

with self.assertLogs("dakara_base.config", "DEBUG"):
with path("tests.resources", "config.yaml") as file:
with as_file(files("tests.resources").joinpath("config.yaml")) as file:
config.load_file(Path(file))

self.assertNotEqual(config.get("key").get("subkey"), "myvalue")
Expand Down Expand Up @@ -281,16 +275,7 @@ def test_configure_logger_no_level(self, mocked_set_level):
mocked_set_level.assert_called_with("INFO")


# fix required for Python 3.8 as you seemingly cannot use an invalid path as a
# context manager
def mock_context_manager(return_value):
mock = MagicMock()
mock.__enter__.return_value = return_value

return mock


@patch("dakara_base.config.shutil.copyfile", autospec=True)
@patch("dakara_base.config.copyfile", autospec=True)
@patch.object(Path, "exists", autospec=True)
@patch.object(Path, "mkdir", autospec=True)
@patch.object(
Expand All @@ -299,16 +284,17 @@ def mock_context_manager(return_value):
new_callable=PropertyMock(return_value=Path("path") / "to" / "directory"),
)
@patch(
"dakara_base.config.path",
return_value=mock_context_manager(Path("path") / "to" / "source"),
"dakara_base.config.as_file",
autospec=True,
)
@patch("dakara_base.config.files", autospec=True)
class CreateConfigFileTestCase(TestCase):
"""Test the config file creator."""

def test_create_empty(
self,
mocked_path,
mocked_files,
mocked_as_file,
mocked_user_config_dir,
mocked_mkdir,
mocked_exists,
Expand All @@ -317,15 +303,21 @@ def test_create_empty(
"""Test create the config file in an empty directory."""
# setup mocks
mocked_exists.return_value = False
mocked_as_file.return_value.__enter__.return_value = (
Path("path") / "to" / "source"
)

# call the function
with self.assertLogs("dakara_base.config") as logger:
create_config_file("module.resources", "config.yaml")

# assert the call
mocked_path.assert_called_with("module.resources", "config.yaml")
mocked_mkdir.assert_called_with(ANY, parents=True, exist_ok=True)
mocked_exists.assert_called_with(ANY)
mocked_files.assert_called_with("module.resources")
mocked_files.return_value.joinpath.assert_called_with("config.yaml")
mocked_mkdir.assert_called_with(
Path("path/to/directory"), parents=True, exist_ok=True
)
mocked_exists.assert_called_with(Path("path/to/directory/config.yaml"))
mocked_copyfile.assert_called_with(
Path("path") / "to" / "source",
Path("path") / "to" / "directory" / "config.yaml",
Expand All @@ -345,7 +337,8 @@ def test_create_empty(
def test_create_existing_no(
self,
mocked_input,
mocked_path,
mocked_files,
mocked_as_file,
mocked_user_config_dir,
mocked_mkdir,
mocked_exists,
Expand All @@ -355,6 +348,9 @@ def test_create_existing_no(
# setup mocks
mocked_exists.return_value = True
mocked_input.return_value = "no"
mocked_as_file.return_value.__enter__.return_value = (
Path("path") / "to" / "source"
)

# call the function
create_config_file("module.resources", "config.yaml")
Expand All @@ -367,38 +363,23 @@ def test_create_existing_no(
)
)

@patch("dakara_base.config.input")
def test_create_existing_invalid_input(
self,
mocked_input,
mocked_path,
mocked_user_config_dir,
mocked_mkdir,
mocked_exists,
mocked_copyfile,
):
"""Test create the config file in a non empty directory with invalid input."""
# setup mocks
mocked_exists.return_value = True
mocked_input.return_value = ""

# call the function
create_config_file("module.resources", "config.yaml")

# assert the call
mocked_copyfile.assert_not_called()

@patch("dakara_base.config.input")
def test_create_existing_force(
self,
mocked_input,
mocked_path,
mocked_files,
mocked_as_file,
mocked_user_config_dir,
mocked_mkdir,
mocked_exists,
mocked_copyfile,
):
"""Test create the config file in a non empty directory with force overwrite."""
# setup mocks
mocked_as_file.return_value.__enter__.return_value = (
Path("path") / "to" / "source"
)

# call the function
create_config_file("module.resources", "config.yaml", force=True)

Expand Down