Skip to content

create base config class #531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
53 changes: 53 additions & 0 deletions exasol/toolbox/BaseConfig/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from collections.abc import Iterable
from dataclasses import dataclass
from pathlib import Path
from typing import (
Annotated,
Optional,
)

from pydantic import (
AfterValidator,
BaseModel,
ConfigDict,
computed_field,
)
from pydantic.dataclasses import dataclass

from exasol.toolbox.util.version import Version


def str_like_version_validation(versions: list[str]):
for version in versions:
Version.from_string(version)
return versions


class BaseConfig(BaseModel):
"""
Basic Configuration for Projects

Attributes:
* python_versions (Iterable[str]): Iterable over all available python versions of the project [default: ("3.9", "3.10", "3.11", "3.12", "3.13")]
* min_py_version : Minimum of python_versions
* max_py_version: Maximum of python_versions
* exasol_versions: (Iterable[str]): Iterabble over all available exasol versions [default: ("7.1.9)
"""

python_versions: Annotated[
list[str], AfterValidator(str_like_version_validation)
] = ["3.9", "3.10", "3.11", "3.12", "3.13"]
exasol_versions: Annotated[
list[str], AfterValidator(str_like_version_validation)
] = ["7.1.9"]
model_config = ConfigDict(frozen=True)

@computed_field
@property
def min_py_version(self) -> str:
return str(min([Version.from_string(v) for v in self.python_versions]))

@computed_field
@property
def max_py_version(self) -> str:
return str(max([Version.from_string(v) for v in self.python_versions]))
6 changes: 2 additions & 4 deletions noxconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from dataclasses import dataclass
from pathlib import Path

from exasol.toolbox.BaseConfig import BaseConfig
from exasol.toolbox.nox.plugin import hookimpl
from exasol.toolbox.tools.replace_version import update_github_yml

Expand Down Expand Up @@ -37,8 +38,7 @@ def prepare_release_add_files(self, session, config):
return self.template_workflows + self.actions


@dataclass(frozen=True)
class Config:
class Config(BaseConfig):
"""Project specific configuration used by nox infrastructure"""

root: Path = Path(__file__).parent
Expand All @@ -51,8 +51,6 @@ class Config:
"project-template",
"idioms",
)
python_versions: Iterable[str] = ("3.9", "3.10", "3.11", "3.12", "3.13")
exasol_versions: Iterable[str] = ("7.1.9",)
plugins: Iterable[object] = (UpdateTemplates,)
# need --keep-runtime-typing, as pydantic with python3.9 does not accept str | None
# format, and it is not resolved with from __future__ import annotations. pyupgrade
Expand Down
3 changes: 1 addition & 2 deletions project-template/{{cookiecutter.repo_name}}/noxconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
from typing import Iterable


@dataclass(frozen=True)
class Config:
class Config():
root: Path = Path(__file__).parent
doc: Path = Path(__file__).parent / "doc"
source: Path = Path("exasol/{{cookiecutter.package_name}}")
Expand Down
10 changes: 8 additions & 2 deletions test/integration/project-template/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,26 @@ def cwd(tmp_path_factory):
return tmp_path_factory.mktemp("project_template_test")


@pytest.fixture(scope="session")
def config():
return Config()


@pytest.fixture(scope="session", autouse=True)
def new_project(cwd):
def new_project(cwd, config):
project_name = "project"
repo_name = "repo"
package_name = "package"

subprocess.run(
["cookiecutter", Config.root / "project-template", "-o", cwd, "--no-input",
["cookiecutter", config.root / "project-template", "-o", cwd, "--no-input",
f"project_name={project_name}", f"repo_name={repo_name}",
f"package_name={package_name}",
], capture_output=True, check=True)

return cwd / repo_name


@pytest.fixture(scope="session", autouse=True)
def poetry_install(run_command, poetry_path):
run_command([poetry_path, "install"])
Expand Down
40 changes: 40 additions & 0 deletions test/unit/BaseConfig/base_config_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import pydantic
import pytest

from exasol.toolbox.BaseConfig import (
BaseConfig,
str_like_version_validation,
)


@pytest.mark.parametrize(
"versions", (["$.2.3"], ["1.f.1"], ["1.1.1", "1.2.3", "2.3.4", "2.3.7", "1.1.1.1"])
)
def test_str_like_version_validation(versions):
with pytest.raises(ValueError):
str_like_version_validation(versions)


def test_default():
config = BaseConfig()
str_like_version_validation(config.python_versions)
str_like_version_validation(config.exasol_versions)


def test_new_value():
conf = BaseConfig(python_versions=["1.21.1", "1.1.1"])
assert conf.python_versions == ["1.21.1", "1.1.1"]


class BaseConfigExpansion(BaseConfig):
expansion1: str = "test1"


def test_expansion_validation():
with pytest.raises(ValueError):
_ = BaseConfigExpansion(python_versions=["1.1.1", "1.1.F"])


def test_min_max_py():
conf = BaseConfig(python_versions=["1.1.1", "5.5.5", "9.9.9"])
assert conf.min_py_version == "1.1.1" and conf.max_py_version == "9.9.9"
4 changes: 2 additions & 2 deletions test/unit/documentation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
_docs_links_check,
_docs_list_links,
)
from noxconfig import Config
from noxconfig import PROJECT_CONFIG


@pytest.fixture()
Expand Down Expand Up @@ -44,7 +44,7 @@ def config(index, file, tmp_path):
test_doc = tmp_path / "doc"
test_doc.mkdir()
(test_doc / "_static").mkdir()
shutil.copyfile(Config.doc / "conf.py", test_doc / "conf.py")
shutil.copyfile(PROJECT_CONFIG.doc / "conf.py", test_doc / "conf.py")
rst_index = test_doc / "index.rst"
rst_file1 = test_doc / "file.rst"
rst_index.touch()
Expand Down
Loading