From a121a6f5ae036b2617f140dc842befd0d61a2097 Mon Sep 17 00:00:00 2001 From: Carmen Bianca BAKKER Date: Fri, 16 Jun 2023 23:20:20 +0200 Subject: [PATCH] Create Config class Signed-off-by: Carmen Bianca BAKKER --- src/reuse/_config.py | 58 +++++++++++++++++++++++++++++++++++++++ tests/test_config.py | 64 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/reuse/_config.py create mode 100644 tests/test_config.py diff --git a/src/reuse/_config.py b/src/reuse/_config.py new file mode 100644 index 000000000..f2e2e4f1f --- /dev/null +++ b/src/reuse/_config.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2023 Carmen Bianca BAKKER +# +# SPDX-License-Identifier: GPL-3.0-or-later + +"""REUSE configuration.""" + +from dataclasses import dataclass, field +from gettext import gettext as _ +from typing import Any, Dict, Optional + + +@dataclass +class AnnotateOptions: + """An object to hold the default values for annotation.""" + + name: Optional[str] = None + contact: Optional[str] = None + license: Optional[str] = None + + +@dataclass +class Config: + """Object to hold all configuration options.""" + + global_annotate_options: AnnotateOptions = field( + default_factory=AnnotateOptions + ) + #: Only truthy attributes override the global options. The key is the path + #: to which the override options apply. + override_annotate_options: Dict[str, AnnotateOptions] = field( + default_factory=dict + ) + + @classmethod + def from_dict(cls, value: Dict[str, Any]) -> "Config": + """Factory method to create a Config from a dictionary.""" + config = cls() + if annotate := value.get("annotate"): + config.global_annotate_options = _annotate_options_from_dict( + annotate + ) + for override in annotate.get("overrides", []): + if not (path := override.get("path")): + raise ValueError( + _("'path' key is missing from one of the overrides.") + ) + config.override_annotate_options[ + path + ] = _annotate_options_from_dict(override) + return config + + +def _annotate_options_from_dict(value: Dict[str, str]) -> AnnotateOptions: + return AnnotateOptions( + name=value.get("default_name"), + contact=value.get("default_contact"), + license=value.get("default_license"), + ) diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 000000000..07c9db861 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,64 @@ +# SPDX-FileCopyrightText: 2023 Carmen Bianca BAKKER +# +# SPDX-License-Identifier: GPL-3.0-or-later + +"""Tests for some _config.""" + +from reuse._config import Config + +# REUSE-IgnoreStart + + +def test_config_from_dict_global_simple(): + """A simple test case for Config.from_dict.""" + value = { + "annotate": { + "default_name": "Jane Doe", + "default_contact": "jane@example.com", + "default_license": "MIT", + } + } + result = Config.from_dict(value) + assert result.global_annotate_options.name == "Jane Doe" + assert result.global_annotate_options.contact == "jane@example.com" + assert result.global_annotate_options.license == "MIT" + + +def test_config_from_dict_global_missing(): + """Only one value is defined.""" + value = { + "annotate": { + "default_name": "Jane Doe", + } + } + result = Config.from_dict(value) + assert result.global_annotate_options.name == "Jane Doe" + assert result.global_annotate_options.contact is None + assert result.global_annotate_options.license is None + + +def test_config_from_dict_override(): + """Overrides are correctly parsed.""" + value = { + "annotate": { + "default_name": "Jane Doe", + "overrides": [ + { + "path": "foo", + "default_name": "John Doe", + }, + { + "path": "bar", + "default_license": "MIT", + }, + ], + } + } + result = Config.from_dict(value) + assert result.global_annotate_options.name == "Jane Doe" + assert result.override_annotate_options["foo"].name == "John Doe" + assert result.override_annotate_options["bar"].name is None + assert result.override_annotate_options["bar"].license == "MIT" + + +# REUSE-IgnoreEnd