diff --git a/commitizen/cli.py b/commitizen/cli.py index 7a554e05e3..da170eefdd 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -155,7 +155,7 @@ def main(): out.error("Command is required") raise SystemExit() - if args.name and not conf["name"]: + if args.name: conf.update({"name": args.name}) if args.version: diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 27d1dd9ee2..2779fb9de4 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -3,7 +3,8 @@ import questionary from packaging.version import Version -from commitizen import bump, config, factory, git, out +from commitizen import bump, factory, git, out +from commitizen.config import BaseConfig NO_COMMITS_FOUND = 3 NO_VERSION_SPECIFIED = 4 @@ -15,11 +16,11 @@ class Bump: """Show prompt for the user to create a guided commit.""" - def __init__(self, config: dict, arguments: dict): - self.config: dict = config + def __init__(self, config: BaseConfig, arguments: dict): + self.config: BaseConfig = config self.arguments: dict = arguments self.parameters: dict = { - **config, + **config.settings, **{ key: arguments[key] for key in [ @@ -56,7 +57,7 @@ def find_increment(self, commits: list) -> Optional[str]: bump_pattern = self.cz.bump_pattern bump_map = self.cz.bump_map if not bump_map or not bump_pattern: - out.error(f"'{self.config['name']}' rule does not support bump") + out.error(f"'{self.config.settings['name']}' rule does not support bump") raise SystemExit(NO_PATTERN_MAP) increment = bump.find_increment( commits, regex=bump_pattern, increments_map=bump_map @@ -74,7 +75,7 @@ def __call__(self): raise SystemExit(NO_VERSION_SPECIFIED) # Initialize values from sources (conf) - current_version: str = self.config["version"] + current_version: str = self.config.settings["version"] tag_format: str = self.parameters["tag_format"] bump_commit_message: str = self.parameters["bump_message"] current_tag_version: str = bump.create_tag( @@ -127,7 +128,7 @@ def __call__(self): if is_files_only: raise SystemExit() - config.set_key("version", new_version.public) + self.config.set_key("version", new_version.public) c = git.commit(message, args="-a") if c.err: out.error('git.commit errror: "{}"'.format(c.err.strip())) diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index 35a45530dd..04ae58538e 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -2,6 +2,7 @@ import re from commitizen import factory, out +from commitizen.config import BaseConfig NO_COMMIT_MSG = 3 @@ -11,19 +12,19 @@ class Check: """Check if the current commit msg matches the commitizen format.""" - def __init__(self, config: dict, arguments: dict, cwd=os.getcwd()): + def __init__(self, config: BaseConfig, arguments: dict, cwd=os.getcwd()): """Init method. Parameters ---------- - config : dict + config : BaseConfig the config object required for the command to perform its action arguments : dict the arguments object that contains all the flags provided by the user """ - self.config: dict = config + self.config: BaseConfig = config self.cz = factory.commiter_factory(self.config) self.arguments: dict = arguments diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index d67fe31c8c..627568132b 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -6,6 +6,8 @@ from commitizen import factory, git, out from commitizen.cz.exceptions import CzException +from commitizen.config import BaseConfig + NO_ANSWERS = 5 COMMIT_ERROR = 6 @@ -17,8 +19,8 @@ class Commit: """Show prompt for the user to create a guided commit.""" - def __init__(self, config: dict, arguments: dict): - self.config: dict = config + def __init__(self, config: BaseConfig, arguments: dict): + self.config: BaseConfig = config self.cz = factory.commiter_factory(self.config) self.arguments = arguments self.temp_file: str = os.path.join(tempfile.gettempdir(), "cz.commit.backup") diff --git a/commitizen/commands/example.py b/commitizen/commands/example.py index 66246d4f55..e7abe7b318 100644 --- a/commitizen/commands/example.py +++ b/commitizen/commands/example.py @@ -1,11 +1,12 @@ from commitizen import factory, out +from commitizen.config import BaseConfig class Example: """Show an example so people understands the rules.""" - def __init__(self, config: dict, *args): - self.config: dict = config + def __init__(self, config: BaseConfig, *args): + self.config: BaseConfig = config self.cz = factory.commiter_factory(self.config) def __call__(self): diff --git a/commitizen/commands/info.py b/commitizen/commands/info.py index f8450e6b0d..afac9797e4 100644 --- a/commitizen/commands/info.py +++ b/commitizen/commands/info.py @@ -1,11 +1,12 @@ from commitizen import factory, out +from commitizen.config import BaseConfig class Info: """Show in depth explanation of your rules.""" - def __init__(self, config: dict, *args): - self.config: dict = config + def __init__(self, config: BaseConfig, *args): + self.config: BaseConfig = config self.cz = factory.commiter_factory(self.config) def __call__(self): diff --git a/commitizen/commands/list_cz.py b/commitizen/commands/list_cz.py index c498c9332f..3f418f440b 100644 --- a/commitizen/commands/list_cz.py +++ b/commitizen/commands/list_cz.py @@ -1,12 +1,13 @@ from commitizen import out from commitizen.cz import registry +from commitizen.config import BaseConfig class ListCz: """List currently installed rules.""" - def __init__(self, config: dict, *args): - self.config: dict = config + def __init__(self, config: BaseConfig, *args): + self.config: BaseConfig = config def __call__(self): out.write("\n".join(registry.keys())) diff --git a/commitizen/commands/schema.py b/commitizen/commands/schema.py index fdb488295b..0940648cde 100644 --- a/commitizen/commands/schema.py +++ b/commitizen/commands/schema.py @@ -1,11 +1,12 @@ from commitizen import factory, out +from commitizen.config import BaseConfig class Schema: """Show structure of the rule.""" - def __init__(self, config: dict, *args): - self.config: dict = config + def __init__(self, config: BaseConfig, *args): + self.config: BaseConfig = config self.cz = factory.commiter_factory(self.config) def __call__(self): diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index b5158ef641..6375347f5e 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -1,12 +1,13 @@ from commitizen import out +from commitizen.config import BaseConfig from commitizen.__version__ import __version__ class Version: """Get the version of the installed commitizen.""" - def __init__(self, config: dict, *args): - self.config: dict = config + def __init__(self, config: BaseConfig, *args): + self.config: BaseConfig = config def __call__(self): out.write(__version__) diff --git a/commitizen/config.py b/commitizen/config.py deleted file mode 100644 index a46d0ad417..0000000000 --- a/commitizen/config.py +++ /dev/null @@ -1,162 +0,0 @@ -import configparser -import json -import os -import warnings -from pathlib import Path -from typing import Optional - -from tomlkit import exceptions, parse - -from commitizen import defaults - - -class Config: - def __init__(self): - self._config = defaults.settings.copy() - self._path: Optional[str] = None - - @property - def config(self): - return self._config - - @property - def path(self): - return self._path - - def update(self, data: dict): - self._config.update(data) - - def add_path(self, path: str): - self._path = path - - -_conf = Config() - - -def read_pyproject_conf(data: str) -> dict: - """We expect to have a section in pyproject looking like - - ``` - [tool.commitizen] - name = "cz_conventional_commits" - ``` - """ - doc = parse(data) - try: - return doc["tool"]["commitizen"] - except exceptions.NonExistentKey: - return {} - - -def read_raw_parser_conf(data: str) -> dict: - """We expect to have a section like this - - ``` - [commitizen] - name = cz_jira - files = [ - "commitizen/__version__.py", - "pyproject.toml" - ] # this tab at the end is important - style = [ - ["pointer", "reverse"], - ["question", "underline"] - ] # this tab at the end is important - ``` - """ - config = configparser.ConfigParser(allow_no_value=True) - config.read_string(data) - try: - _data: dict = dict(config["commitizen"]) - if "files" in _data: - files = _data["files"] - _f = json.loads(files) - _data.update({"files": _f}) - if "style" in _data: - style = _data["style"] - _s = json.loads(style) - _data.update({"style": _s}) - - return _data - - except KeyError: - return {} - - -def load_global_conf() -> dict: - home = str(Path.home()) - global_cfg = os.path.join(home, ".cz") - if not os.path.exists(global_cfg): - return {} - - # global conf doesnt make sense with commitizen bump - # so I'm deprecating it and won't test it - message = ( - "Global conf will be deprecated in next major version. " - "Use per project configuration. " - "Remove '~/.cz' file from your conf folder." - ) - warnings.simplefilter("always", DeprecationWarning) - warnings.warn(message, category=DeprecationWarning) - - with open(global_cfg, "r") as f: - data = f.read() - conf = read_raw_parser_conf(data) - return conf - - -def read_cfg() -> dict: - allowed_cfg_files = defaults.config_files - - for filename in allowed_cfg_files: - config_file_exists = os.path.exists(filename) - if not config_file_exists: - continue - with open(filename, "r") as f: - data: str = f.read() - if "toml" in filename: - conf = read_pyproject_conf(data) - else: - warnings.warn( - ".cz, setup.cfg, and .cz.cfg will be deprecated " - "in next major version. \n" - 'Please use "pyproject.toml", ".cz.toml" instead' - ) - conf = read_raw_parser_conf(data) - if not conf: - continue - - _conf.update(conf) - _conf.add_path(filename) - return _conf.config - - if not _conf.path: - conf = load_global_conf() - if conf: - _conf.update(conf) - return _conf.config - - -def set_key(key: str, value: str) -> dict: - """Set or update a key in the conf. - - For now only strings are supported. - We use to update the version number. - """ - if not _conf.path: - return {} - - if "toml" in _conf.path: - with open(_conf.path, "r") as f: - parser = parse(f.read()) - parser["tool"]["commitizen"][key] = value - with open(_conf.path, "w") as f: - f.write(parser.as_string()) - else: - parser = configparser.ConfigParser() - parser.read(_conf.path) - parser["commitizen"][key] = value - with open(_conf.path, "w") as f: - parser.write(f) - - return _conf.config diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py new file mode 100644 index 0000000000..461789784f --- /dev/null +++ b/commitizen/config/__init__.py @@ -0,0 +1,68 @@ +import os +import warnings +from pathlib import Path +from typing import Optional + +from commitizen import defaults +from .base_config import BaseConfig +from .toml_config import TomlConfig +from .ini_config import IniConfig + + +def load_global_conf() -> Optional[IniConfig]: + home = str(Path.home()) + global_cfg = os.path.join(home, ".cz") + if not os.path.exists(global_cfg): + return None + + # global conf doesnt make sense with commitizen bump + # so I'm deprecating it and won't test it + message = ( + "Global conf will be deprecated in next major version. " + "Use per project configuration. " + "Remove '~/.cz' file from your conf folder." + ) + warnings.simplefilter("always", DeprecationWarning) + warnings.warn(message, category=DeprecationWarning) + + with open(global_cfg, "r") as f: + data = f.read() + + conf = IniConfig(data) + return conf + + +def read_cfg() -> BaseConfig: + conf = BaseConfig() + + allowed_cfg_files = defaults.config_files + for filename in allowed_cfg_files: + config_file_exists = os.path.exists(filename) + if not config_file_exists: + continue + + with open(filename, "r") as f: + data: str = f.read() + + if "toml" in filename: + _conf = TomlConfig(data=data, path=filename) + else: + warnings.warn( + ".cz, setup.cfg, and .cz.cfg will be deprecated " + "in next major version. \n" + 'Please use "pyproject.toml", ".cz.toml" instead' + ) + _conf = IniConfig(data=data, path=filename) + + if _conf.is_empty_config: + continue + else: + conf = _conf + break + + if not conf.path: + global_conf = load_global_conf() + if global_conf: + conf = global_conf + + return conf diff --git a/commitizen/config/base_config.py b/commitizen/config/base_config.py new file mode 100644 index 0000000000..e554853b83 --- /dev/null +++ b/commitizen/config/base_config.py @@ -0,0 +1,34 @@ +from typing import Optional + +from commitizen.defaults import DEFAULT_SETTINGS + + +class BaseConfig: + def __init__(self): + self._settings: dict = DEFAULT_SETTINGS.copy() + self._path: Optional[str] = None + + @property + def settings(self) -> dict: + return self._settings + + @property + def path(self) -> str: + return self._path + + def set_key(self, key, value): + """Set or update a key in the conf. + + For now only strings are supported. + We use to update the version number. + """ + return self + + def update(self, data: dict): + self._settings.update(data) + + def add_path(self, path: str): + self._path = path + + def _parse_setting(self, data: str) -> dict: + raise NotImplementedError() diff --git a/commitizen/config/ini_config.py b/commitizen/config/ini_config.py new file mode 100644 index 0000000000..5c02e22e9b --- /dev/null +++ b/commitizen/config/ini_config.py @@ -0,0 +1,69 @@ +import configparser +import json +import warnings + +from .base_config import BaseConfig + + +class IniConfig(BaseConfig): + def __init__(self, *, data: str, path: str): + warnings.simplefilter("always", DeprecationWarning) + warnings.warn( + ( + ".cz, setup.cfg, and .cz.cfg will be deprecated " + "in next major version. \n" + 'Please use "pyproject.toml", ".cz.toml" instead' + ), + category=DeprecationWarning, + ) + + super(IniConfig, self).__init__() + self.is_empty_config = False + self._parse_setting(data) + self.add_path(path) + + def set_key(self, key, value): + """Set or update a key in the conf. + + For now only strings are supported. + We use to update the version number. + """ + parser = configparser.ConfigParser() + parser.read(self.path) + parser["commitizen"][key] = value + with open(self.path, "w") as f: + parser.write(f) + return self + + def _parse_setting(self, data: str): + """We expect to have a section like this + + ``` + [commitizen] + name = cz_jira + files = [ + "commitizen/__version__.py", + "pyproject.toml" + ] # this tab at the end is important + style = [ + ["pointer", "reverse"], + ["question", "underline"] + ] # this tab at the end is important + ``` + """ + config = configparser.ConfigParser(allow_no_value=True) + config.read_string(data) + try: + _data: dict = dict(config["commitizen"]) + if "files" in _data: + files = _data["files"] + _f = json.loads(files) + _data.update({"files": _f}) + if "style" in _data: + style = _data["style"] + _s = json.loads(style) + _data.update({"style": _s}) + + self._settings.update(_data) + except KeyError: + self.is_empty_config = True diff --git a/commitizen/config/toml_config.py b/commitizen/config/toml_config.py new file mode 100644 index 0000000000..7e669b18e0 --- /dev/null +++ b/commitizen/config/toml_config.py @@ -0,0 +1,39 @@ +from tomlkit import exceptions, parse + +from .base_config import BaseConfig + + +class TomlConfig(BaseConfig): + def __init__(self, *, data: str, path: str): + super(TomlConfig, self).__init__() + self.is_empty_config = False + self._parse_setting(data) + self.add_path(path) + + def set_key(self, key, value): + """Set or update a key in the conf. + + For now only strings are supported. + We use to update the version number. + """ + with open(self.path, "r") as f: + parser = parse(f.read()) + + parser["tool"]["commitizen"][key] = value + with open(self.path, "w") as f: + f.write(parser.as_string()) + return self + + def _parse_setting(self, data: str): + """We expect to have a section in pyproject looking like + + ``` + [tool.commitizen] + name = "cz_conventional_commits" + ``` + """ + doc = parse(data) + try: + self.settings.update(doc["tool"]["commitizen"]) + except exceptions.NonExistentKey: + self.is_empty_config = True diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index d756be905b..258f43ca5e 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -22,8 +22,8 @@ class BaseCommitizen(metaclass=ABCMeta): def __init__(self, config: dict): self.config = config - if not self.config.get("style"): - self.config["style"] = BaseCommitizen.default_style_config + if not self.config.settings.get("style"): + self.config.settings.update({"style": BaseCommitizen.default_style_config}) @abstractmethod def questions(self) -> list: @@ -36,7 +36,10 @@ def message(self, answers: dict) -> str: @property def style(self): return merge_styles( - [Style(BaseCommitizen.default_style_config), Style(self.config["style"])] + [ + Style(BaseCommitizen.default_style_config), + Style(self.config.settings["style"]), + ] ) def example(self) -> str: diff --git a/commitizen/cz/customize/customize.py b/commitizen/cz/customize/customize.py index 7120147763..46ea0602d9 100644 --- a/commitizen/cz/customize/customize.py +++ b/commitizen/cz/customize/customize.py @@ -5,6 +5,7 @@ from commitizen import defaults from commitizen.cz.base import BaseCommitizen +from commitizen.config import BaseConfig __all__ = ["CustomizeCommitsCz"] @@ -13,41 +14,40 @@ class CustomizeCommitsCz(BaseCommitizen): bump_pattern = defaults.bump_pattern bump_map = defaults.bump_map - def __init__(self, config: dict): + def __init__(self, config: BaseConfig): super(CustomizeCommitsCz, self).__init__(config) - self.custom_config = self.config.get("customize") + self.custom_settings = self.config.settings.get("customize") - custom_bump_pattern = self.custom_config.get("bump_pattern") + custom_bump_pattern = self.custom_settings.get("bump_pattern") if custom_bump_pattern: self.bump_pattern = custom_bump_pattern - custom_bump_map = self.custom_config.get("bump_map") + custom_bump_map = self.custom_settings.get("bump_map") if custom_bump_map: self.bump_map = custom_bump_map def questions(self) -> list: - return self.custom_config.get("questions") + return self.custom_settings.get("questions") def message(self, answers: dict) -> str: - message_template = Template(self.custom_config.get("message_template")) + message_template = Template(self.custom_settings.get("message_template")) if getattr(Template, "substitute", None): return message_template.substitute(**answers) else: return message_template.render(**answers) def example(self) -> str: - return self.custom_config.get("example") + return self.custom_settings.get("example") def schema(self) -> str: - return self.custom_config.get("schema") + return self.custom_settings.get("schema") def info(self) -> str: - info_path = self.custom_config.get("info_path") - info = self.custom_config.get("info") + info_path = self.custom_settings.get("info_path") + info = self.custom_settings.get("info") if info_path: with open(info_path, "r") as f: content = f.read() return content elif info: return info - raise NotImplementedError("Not Implemented yet") diff --git a/commitizen/defaults.py b/commitizen/defaults.py index e63167d0e5..498b4f0558 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -2,9 +2,9 @@ # TODO: .cz, setup.cfg, .cz.cfg should be removed in 2.0 config_files: list = ["pyproject.toml", ".cz.toml", ".cz", "setup.cfg", ".cz.cfg"] -# Available settings -settings: dict = { - "name": name, + +DEFAULT_SETTINGS = { + "name": "cz_conventional_commits", "version": None, "files": [], "tag_format": None, # example v$version diff --git a/commitizen/factory.py b/commitizen/factory.py index b1592feda7..b42ab7c9a9 100644 --- a/commitizen/factory.py +++ b/commitizen/factory.py @@ -1,12 +1,13 @@ from commitizen import BaseCommitizen, out from commitizen.cz import registry +from commitizen.config import BaseConfig NO_COMMITIZEN_FOUND = 2 -def commiter_factory(config: dict) -> BaseCommitizen: +def commiter_factory(config: BaseConfig) -> BaseCommitizen: """Return the correct commitizen existing in the registry.""" - name: str = config["name"] + name: str = config.settings["name"] try: _cz = registry[name](config) except KeyError: diff --git a/tests/test_commands.py b/tests/test_commands.py index 6aaae55eef..e26d5be318 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -8,8 +8,14 @@ from commitizen import cmd, commands, defaults from commitizen.cz.exceptions import CzException +from commitizen.config import BaseConfig -config = {"name": defaults.name} + +@pytest.fixture() +def config(): + _config = BaseConfig() + _config.settings.update({"name": defaults.name}) + return _config @pytest.fixture @@ -28,7 +34,7 @@ def get_temp_dir(): @pytest.mark.usefixtures("staging_is_clean") -def test_commit(mocker): +def test_commit(config, mocker): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -48,7 +54,7 @@ def test_commit(mocker): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_retry_fails_no_backup(mocker): +def test_commit_retry_fails_no_backup(config, mocker): commit_mock = mocker.patch("commitizen.git.commit") commit_mock.return_value = cmd.Command("success", "", "", "") @@ -57,7 +63,7 @@ def test_commit_retry_fails_no_backup(mocker): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_retry_works(mocker): +def test_commit_retry_works(config, mocker): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -95,7 +101,7 @@ def test_commit_retry_works(mocker): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_dry_run_option(mocker): +def test_commit_command_with_dry_run_option(config, mocker): prompt_mock = mocker = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -111,7 +117,7 @@ def test_commit_command_with_dry_run_option(mocker): commit_cmd() -def test_commit_when_nothing_to_commit(mocker): +def test_commit_when_nothing_to_commit(config, mocker): is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean") is_staging_clean_mock.return_value = True @@ -123,7 +129,7 @@ def test_commit_when_nothing_to_commit(mocker): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_when_customized_expected_raised(mocker, capsys): +def test_commit_when_customized_expected_raised(config, mocker, capsys): _err = ValueError() _err.__context__ = CzException("This is the root custom err") prompt_mock = mocker.patch("questionary.prompt") @@ -140,39 +146,39 @@ def test_commit_when_customized_expected_raised(mocker, capsys): assert "This is the root custom err" in captured.err -def test_example(): +def test_example(config): with mock.patch("commitizen.out.write") as write_mock: commands.Example(config)() write_mock.assert_called_once() -def test_info(): +def test_info(config): with mock.patch("commitizen.out.write") as write_mock: commands.Info(config)() write_mock.assert_called_once() -def test_schema(): +def test_schema(config): with mock.patch("commitizen.out.write") as write_mock: commands.Schema(config)() write_mock.assert_called_once() -def test_list_cz(): +def test_list_cz(config): with mock.patch("commitizen.out.write") as mocked_write: commands.ListCz(config)() mocked_write.assert_called_once() -def test_version(): +def test_version(config): with mock.patch("commitizen.out.write") as mocked_write: commands.Version(config)() mocked_write.assert_called_once() -def test_check_no_conventional_commit(mocker): +def test_check_no_conventional_commit(config, mocker): with pytest.raises(SystemExit): error_mock = mocker.patch("commitizen.out.error") @@ -189,7 +195,7 @@ def test_check_no_conventional_commit(mocker): error_mock.assert_called_once() -def test_check_conventional_commit(mocker): +def test_check_conventional_commit(config, mocker): success_mock = mocker.patch("commitizen.out.success") with get_temp_dir() as dir: @@ -205,6 +211,6 @@ def test_check_conventional_commit(mocker): success_mock.assert_called_once() -def test_check_command_when_commit_file_not_found(): +def test_check_command_when_commit_file_not_found(config): with pytest.raises(FileNotFoundError): commands.Check(config=config, arguments={"commit_msg_file": ""})() diff --git a/tests/test_conf.py b/tests/test_conf.py index 3a94834161..2335085967 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -36,7 +36,7 @@ ] """ -_config = { +_settings = { "name": "cz_jira", "version": "1.0.0", "tag_format": None, @@ -45,7 +45,7 @@ "style": [["pointer", "reverse"], ["question", "underline"]], } -_new_config = { +_new_settings = { "name": "cz_jira", "version": "2.0.0", "tag_format": None, @@ -54,7 +54,7 @@ "style": [["pointer", "reverse"], ["question", "underline"]], } -_read_conf = { +_read_settings = { "name": "cz_jira", "version": "1.0.0", "files": ["commitizen/__version__.py", "pyproject.toml"], @@ -64,7 +64,6 @@ @pytest.fixture def configure_supported_files(): - config._conf = config.Config() original = defaults.config_files.copy() # patch the defaults to include tests @@ -99,47 +98,31 @@ def empty_pyproject_ok_cz(): os.remove(cz) -def test_read_pyproject_conf(): - assert config.read_pyproject_conf(PYPROJECT) == _read_conf - - -def test_read_pyproject_conf_empty(): - assert config.read_pyproject_conf("") == {} - - -def test_read_raw_parser_conf(): - assert config.read_raw_parser_conf(RAW_CONFIG) == _read_conf - - -def test_read_raw_parser_conf_empty(): - assert config.read_raw_parser_conf("") == {} - - @pytest.mark.parametrize( "config_files_manager", defaults.config_files.copy(), indirect=True ) def test_load_conf(config_files_manager, configure_supported_files): cfg = config.read_cfg() - assert cfg == _config + assert cfg.settings == _settings def test_conf_is_loaded_with_empty_pyproject_but_ok_cz( empty_pyproject_ok_cz, configure_supported_files ): cfg = config.read_cfg() - assert cfg == _config + assert cfg.settings == _settings def test_conf_returns_default_when_no_files(configure_supported_files): cfg = config.read_cfg() - assert cfg == defaults.settings + assert cfg.settings == defaults.DEFAULT_SETTINGS @pytest.mark.parametrize( "config_files_manager", defaults.config_files.copy(), indirect=True ) def test_set_key(configure_supported_files, config_files_manager): - config.read_cfg() - config.set_key("version", "2.0.0") + _conf = config.read_cfg() + _conf.set_key("version", "2.0.0") cfg = config.read_cfg() - assert cfg == _new_config + assert cfg.settings == _new_settings diff --git a/tests/test_cz_base.py b/tests/test_cz_base.py index e4b48d50a6..82925388ef 100644 --- a/tests/test_cz_base.py +++ b/tests/test_cz_base.py @@ -2,8 +2,14 @@ from commitizen import defaults from commitizen.cz.base import BaseCommitizen +from commitizen.config import BaseConfig -config = {"name": defaults.name} + +@pytest.fixture() +def config(): + _config = BaseConfig() + _config.settings.update({"name": defaults.name}) + return _config class DummyCz(BaseCommitizen): @@ -14,34 +20,34 @@ def message(self, answers): return answers["commit"] -def test_base_raises_error(): +def test_base_raises_error(config): with pytest.raises(TypeError): BaseCommitizen(config) -def test_questions(): +def test_questions(config): cz = DummyCz(config) assert isinstance(cz.questions(), list) -def test_message(): +def test_message(config): cz = DummyCz(config) assert cz.message({"commit": "holis"}) == "holis" -def test_example(): +def test_example(config): cz = DummyCz(config) with pytest.raises(NotImplementedError): cz.example() -def test_schema(): +def test_schema(config): cz = DummyCz(config) with pytest.raises(NotImplementedError): cz.schema() -def test_info(): +def test_info(config): cz = DummyCz(config) with pytest.raises(NotImplementedError): cz.info() diff --git a/tests/test_cz_conventional_commits.py b/tests/test_cz_conventional_commits.py index f464ba4ae6..dd6cfbff30 100644 --- a/tests/test_cz_conventional_commits.py +++ b/tests/test_cz_conventional_commits.py @@ -7,8 +7,8 @@ parse_subject, ) from commitizen.cz.exceptions import AnswerRequiredError +from commitizen.config import BaseConfig -config = {"name": defaults.name} valid_scopes = ["", "simple", "dash-separated", "camelCase" "UPPERCASE"] @@ -21,6 +21,13 @@ invalid_subjects = ["", " ", ".", " .", "", None] +@pytest.fixture() +def config(): + _config = BaseConfig() + _config._settings["name"] = defaults.name + return _config + + def test_parse_scope_valid_values(): for valid_scope in valid_scopes: assert valid_scope == parse_scope(valid_scope) @@ -49,14 +56,14 @@ def test_subject_transformations(): assert transformed_subject == parse_subject(invalid_subject) -def test_questions(): +def test_questions(config): conventional_commits = ConventionalCommitsCz(config) questions = conventional_commits.questions() assert isinstance(questions, list) assert isinstance(questions[0], dict) -def test_small_answer(): +def test_small_answer(config): conventional_commits = ConventionalCommitsCz(config) answers = { "prefix": "fix", @@ -70,7 +77,7 @@ def test_small_answer(): assert message == "fix(users): email pattern corrected" -def test_long_answer(): +def test_long_answer(config): conventional_commits = ConventionalCommitsCz(config) answers = { "prefix": "fix", @@ -87,21 +94,21 @@ def test_long_answer(): ) -def test_example(): +def test_example(config): """just testing a string is returned. not the content""" conventional_commits = ConventionalCommitsCz(config) example = conventional_commits.example() assert isinstance(example, str) -def test_schema(): +def test_schema(config): """just testing a string is returned. not the content""" conventional_commits = ConventionalCommitsCz(config) schema = conventional_commits.schema() assert isinstance(schema, str) -def test_info(): +def test_info(config): """just testing a string is returned. not the content""" conventional_commits = ConventionalCommitsCz(config) info = conventional_commits.info() diff --git a/tests/test_cz_customize.py b/tests/test_cz_customize.py index 56d58811e5..3ec448cc32 100644 --- a/tests/test_cz_customize.py +++ b/tests/test_cz_customize.py @@ -1,13 +1,11 @@ import pytest -from tomlkit import parse -from commitizen.config import Config +from commitizen.config import TomlConfig from commitizen.cz.customize import CustomizeCommitsCz @pytest.fixture(scope="module") def config(): - _conf = Config() toml_str = r""" [tool.commitizen.customize] message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}" @@ -36,8 +34,7 @@ def config(): name = "show_message" message = "Do you want to add body message in commit?" """ - _conf.update(parse(toml_str)["tool"]["commitizen"]) - return _conf.config + return TomlConfig(data=toml_str, path="not_exist.toml") def test_bump_pattern(config): diff --git a/tests/test_cz_jira.py b/tests/test_cz_jira.py index 1092df56cc..0c05b46a3c 100644 --- a/tests/test_cz_jira.py +++ b/tests/test_cz_jira.py @@ -1,17 +1,25 @@ +import pytest + from commitizen import defaults from commitizen.cz.jira import JiraSmartCz +from commitizen.config import BaseConfig + -config = {"name": defaults.name} +@pytest.fixture() +def config(): + _config = BaseConfig() + _config.settings.update({"name": defaults.name}) + return _config -def test_questions(): +def test_questions(config): cz = JiraSmartCz(config) questions = cz.questions() assert isinstance(questions, list) assert isinstance(questions[0], dict) -def test_answer(): +def test_answer(config): cz = JiraSmartCz(config) answers = { "message": "new test", @@ -24,17 +32,17 @@ def test_answer(): assert message == "new test JRA-34" -def test_example(): +def test_example(config): cz = JiraSmartCz(config) assert "JRA-34 #comment corrected indent issue\n" in cz.example() -def test_schema(): +def test_schema(config): cz = JiraSmartCz(config) assert "" in cz.schema() -def test_info(): +def test_info(config): cz = JiraSmartCz(config) assert ( "Smart Commits allow repository committers to perform " diff --git a/tests/test_factory.py b/tests/test_factory.py index 2ec7b19364..5c5da7b139 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -1,15 +1,18 @@ import pytest from commitizen import BaseCommitizen, defaults, factory +from commitizen.config import BaseConfig def test_factory(): - config = {"name": defaults.name} + config = BaseConfig() + config.settings.update({"name": defaults.name}) r = factory.commiter_factory(config) assert isinstance(r, BaseCommitizen) def test_factory_fails(): - config = {"name": "nothing"} + config = BaseConfig() + config.settings.update({"name": "Nothing"}) with pytest.raises(SystemExit): factory.commiter_factory(config)