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
4 changes: 3 additions & 1 deletion samcli/cli/cli_config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ def __call__(self, config_path: Path, config_env: str, cmd_names: List[str]) ->

# Use default sam config file name if config_path only contain the directory
config_file_path = (
Path(os.path.abspath(config_path)) if config_path else Path(os.getcwd(), DEFAULT_CONFIG_FILE_NAME)
Path(os.path.abspath(config_path))
if config_path
else Path(os.getcwd(), SamConfig.get_default_file(os.getcwd()))
)
config_file_name = config_file_path.name
config_file_dir = config_file_path.parents[0]
Expand Down
7 changes: 4 additions & 3 deletions samcli/commands/deploy/guided_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from samcli.cli.context import get_cmd_names
from samcli.commands.deploy.exceptions import GuidedDeployFailedError
from samcli.lib.config.exceptions import SamConfigFileReadException
from samcli.lib.config.samconfig import DEFAULT_CONFIG_FILE_NAME, DEFAULT_ENV, SamConfig
from samcli.lib.config.samconfig import DEFAULT_ENV, SamConfig


class GuidedConfig:
Expand All @@ -20,9 +20,10 @@ def get_config_ctx(self, config_file=None):
ctx = click.get_current_context()

samconfig_dir = getattr(ctx, "samconfig_dir", None)
config_dir = samconfig_dir if samconfig_dir else SamConfig.config_dir(template_file_path=self.template_file)
samconfig = SamConfig(
config_dir=samconfig_dir if samconfig_dir else SamConfig.config_dir(template_file_path=self.template_file),
filename=config_file or DEFAULT_CONFIG_FILE_NAME,
config_dir=config_dir,
filename=config_file or SamConfig.get_default_file(config_dir=config_dir),
)
return ctx, samconfig

Expand Down
2 changes: 1 addition & 1 deletion samcli/lib/config/file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def read(filepath: Path) -> Any:
A dictionary-like yaml object, which represents the contents of the YAML file at the
provided location.
"""
yaml_doc = YamlFileManager.yaml.load("")
yaml_doc = {}
try:
yaml_doc = YamlFileManager.yaml.load(filepath.read_text())
except OSError as e:
Expand Down
41 changes: 38 additions & 3 deletions samcli/lib/config/samconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
LOG = logging.getLogger(__name__)

DEFAULT_CONFIG_FILE_EXTENSION = ".toml"
DEFAULT_CONFIG_FILE_NAME = f"samconfig{DEFAULT_CONFIG_FILE_EXTENSION}"
DEFAULT_CONFIG_FILE = "samconfig"
DEFAULT_CONFIG_FILE_NAME = DEFAULT_CONFIG_FILE + DEFAULT_CONFIG_FILE_EXTENSION
DEFAULT_ENV = "default"
DEFAULT_GLOBAL_CMDNAME = "global"

Expand All @@ -24,7 +25,7 @@ class SamConfig:
Class to represent `samconfig` config options.
"""

FILE_MANAGER_MAPPER: Dict[str, Type[FileManager]] = {
FILE_MANAGER_MAPPER: Dict[str, Type[FileManager]] = { # keys ordered by priority
".toml": TomlFileManager,
".yaml": YamlFileManager,
".yml": YamlFileManager,
Expand All @@ -44,7 +45,7 @@ def __init__(self, config_dir, filename=None):
could automatically support auto-resolving multiple config files within same directory.
"""
self.document = {}
self.filepath = Path(config_dir, filename or DEFAULT_CONFIG_FILE_NAME)
self.filepath = Path(config_dir, filename or self.get_default_file(config_dir=config_dir))
self.file_manager = self.FILE_MANAGER_MAPPER.get(self.filepath.suffix, None)
if not self.file_manager:
LOG.warning(
Expand Down Expand Up @@ -247,6 +248,40 @@ def _deduplicate_global_parameters(self, cmd_name_key, section, key, env=DEFAULT
# Only keep the global parameter
del self.document[env][cmd_name_key][section][key]

@staticmethod
def get_default_file(config_dir: str) -> str:
"""Return a defaultly-named config file, if it exists, otherwise the current default.

Parameters
----------
config_dir: str
The name of the directory where the config file is/will be stored.

Returns
-------
str
The name of the config file found, if it exists. In the case that it does not exist, the default config
file name is returned instead.
"""
config_files_found = 0
config_file = DEFAULT_CONFIG_FILE_NAME

for extension in reversed(list(SamConfig.FILE_MANAGER_MAPPER.keys())):
filename = DEFAULT_CONFIG_FILE + extension
if Path(config_dir, filename).exists():
config_files_found += 1
config_file = filename

if config_files_found == 0: # Config file doesn't exist (yet!)
LOG.info(f"No config file found. Creating one as {config_file}.")
elif config_files_found > 1: # Multiple config files; let user know which is used
LOG.info(
f"More than one samconfig file found; using {config_file}."
f" To use another config file, please specify it using the '--config-file' flag."
)

return config_file

@staticmethod
def _version_sanity_check(version: Any) -> None:
if not isinstance(version, float):
Expand Down
35 changes: 0 additions & 35 deletions tests/unit/commands/samconfig/test_samconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
from unittest import TestCase
from unittest.mock import patch, ANY
import logging
from parameterized import parameterized
from samcli.lib.config.exceptions import SamConfigFileReadException
from samcli.lib.config.file_manager import JsonFileManager, TomlFileManager, YamlFileManager

from samcli.lib.config.samconfig import SamConfig, DEFAULT_ENV
from samcli.lib.utils.packagetype import ZIP, IMAGE
Expand Down Expand Up @@ -1248,38 +1245,6 @@ def test_secondary_option_name_template_validate(self, do_cli_mock):
do_cli_mock.assert_called_with(ANY, str(Path(os.getcwd(), "mytemplate.yaml")), False)


class TestSamConfigFileManager(TestCase):
def test_file_manager_not_declared(self):
config_dir = tempfile.gettempdir()
config_path = Path(config_dir, "samconfig")

with self.assertRaises(SamConfigFileReadException):
SamConfig(config_path, filename="samconfig")

def test_file_manager_unsupported(self):
config_dir = tempfile.gettempdir()
config_path = Path(config_dir, "samconfig.jpeg")

with self.assertRaises(SamConfigFileReadException):
SamConfig(config_path, filename="samconfig.jpeg")

@parameterized.expand(
[
("samconfig.toml", TomlFileManager),
("samconfig.yaml", YamlFileManager),
("samconfig.yml", YamlFileManager),
("samconfig.json", JsonFileManager),
]
)
def test_file_manager(self, filename, expected_file_manager):
config_dir = tempfile.gettempdir()
config_path = Path(config_dir, filename)

samconfig = SamConfig(config_path, filename=filename)

self.assertIs(samconfig.file_manager, expected_file_manager)


@contextmanager
def samconfig_parameters(cmd_names, config_dir=None, env=None, **kwargs):
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/lib/samconfig/test_file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_read_yaml_file_path_not_valid(self):

config_doc = YamlFileManager.read(config_path)

self.assertEqual(config_doc, self.yaml.load(""))
self.assertEqual(config_doc, {})

def test_write_yaml(self):
config_dir = tempfile.gettempdir()
Expand Down
86 changes: 84 additions & 2 deletions tests/unit/lib/samconfig/test_samconfig.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import os
from pathlib import Path
from parameterized import parameterized
import tempfile
from unittest import TestCase

from samcli.lib.config.exceptions import SamConfigVersionException
from samcli.lib.config.samconfig import SamConfig, DEFAULT_CONFIG_FILE_NAME, DEFAULT_GLOBAL_CMDNAME, DEFAULT_ENV
from samcli.lib.config.exceptions import SamConfigFileReadException, SamConfigVersionException
from samcli.lib.config.file_manager import JsonFileManager, TomlFileManager, YamlFileManager
from samcli.lib.config.samconfig import (
DEFAULT_CONFIG_FILE,
SamConfig,
DEFAULT_CONFIG_FILE_NAME,
DEFAULT_GLOBAL_CMDNAME,
DEFAULT_ENV,
)
from samcli.lib.config.version import VERSION_KEY, SAM_CONFIG_VERSION
from samcli.lib.utils import osutils

Expand Down Expand Up @@ -221,3 +230,76 @@ def test_write_config_file_will_create_the_file_if_not_exist(self):
samconfig.put(cmd_names=["any", "command"], section="any-section", key="any-key", value="any-value")
samconfig.flush()
self.assertTrue(samconfig.exists())

def test_passed_filename_used(self):
config_path = Path(self.config_dir, "myconfigfile.toml")

self.assertFalse(config_path.exists())

self.samconfig = SamConfig(self.config_dir, filename="myconfigfile.toml")
self.samconfig.put( # put some config options so it creates the file
cmd_names=["any", "command"], section="section", key="key", value="value"
)
self.samconfig.flush()

self.assertTrue(config_path.exists())
self.assertFalse(Path(self.config_dir, DEFAULT_CONFIG_FILE_NAME).exists())

def test_config_uses_default_if_none_provided(self):
self.samconfig = SamConfig(self.config_dir)
self.samconfig.put( # put some config options so it creates the file
cmd_names=["any", "command"], section="section", key="key", value="value"
)
self.samconfig.flush()

self.assertTrue(Path(self.config_dir, DEFAULT_CONFIG_FILE_NAME).exists())

def test_config_priority(self):
config_files = []
extensions_in_priority = list(SamConfig.FILE_MANAGER_MAPPER.keys()) # priority by order in dict
for extension in extensions_in_priority:
filename = DEFAULT_CONFIG_FILE + extension
config = SamConfig(self.config_dir, filename=filename)
config.put( # put some config options so it creates the file
cmd_names=["any", "command"], section="section", key="key", value="value"
)
config.flush()
config_files.append(config)

while extensions_in_priority:
config = SamConfig(self.config_dir)
next_priority = extensions_in_priority.pop(0)
self.assertEqual(config.filepath, Path(self.config_dir, DEFAULT_CONFIG_FILE + next_priority))
os.remove(config.path())


class TestSamConfigFileManager(TestCase):
def test_file_manager_not_declared(self):
config_dir = tempfile.gettempdir()
config_path = Path(config_dir, "samconfig")

with self.assertRaises(SamConfigFileReadException):
SamConfig(config_path, filename="samconfig")

def test_file_manager_unsupported(self):
config_dir = tempfile.gettempdir()
config_path = Path(config_dir, "samconfig.jpeg")

with self.assertRaises(SamConfigFileReadException):
SamConfig(config_path, filename="samconfig.jpeg")

@parameterized.expand(
[
("samconfig.toml", TomlFileManager),
("samconfig.yaml", YamlFileManager),
("samconfig.yml", YamlFileManager),
("samconfig.json", JsonFileManager),
]
)
def test_file_manager(self, filename, expected_file_manager):
config_dir = tempfile.gettempdir()
config_path = Path(config_dir, filename)

samconfig = SamConfig(config_path, filename=filename)

self.assertIs(samconfig.file_manager, expected_file_manager)