From d818b60c4f7289c2cdf3c6fa734b5bff53ad21b8 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Wed, 9 Oct 2024 14:40:55 +0300 Subject: [PATCH 1/7] Add env-var aliases to improve compatibility with existing internal services and pipelines --- microbootstrap/settings.py | 14 +++++++++---- pyproject.toml | 1 + tests/test_settings.py | 42 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 tests/test_settings.py diff --git a/microbootstrap/settings.py b/microbootstrap/settings.py index 81debc0..0636e9a 100644 --- a/microbootstrap/settings.py +++ b/microbootstrap/settings.py @@ -2,6 +2,7 @@ import os import typing +import pydantic import pydantic_settings from microbootstrap import ( @@ -16,7 +17,8 @@ SettingsT = typing.TypeVar("SettingsT", bound="BaseServiceSettings") -ENVIRONMENT_PREFIX: typing.Final = "ENVIRONMENT_PREFIX" +ENV_PREFIX_VAR_NAME: typing.Final = "ENVIRONMENT_PREFIX" +ENV_PREFIX: typing.Final = os.getenv(ENV_PREFIX_VAR_NAME, "") # TODO: add offline docs and cors support # noqa: TD002 @@ -25,9 +27,13 @@ class BaseServiceSettings( ): service_debug: bool = True service_environment: str | None = None - service_name: str = "micro-service" + service_name: str = pydantic.Field( + "micro-service", validation_alias=pydantic.AliasChoices("SERVICE_NAME", f"{ENV_PREFIX}SERVICE_NAME") + ) service_description: str = "Micro service description" - service_version: str = "1.0.0" + service_version: str = pydantic.Field( + "1.0.0", validation_alias=pydantic.AliasChoices("CI_COMMIT_TAG", f"{ENV_PREFIX}SERVICE_VERSION") + ) service_static_path: str = "/static" server_host: str = "0.0.0.0" # noqa: S104 @@ -37,7 +43,7 @@ class BaseServiceSettings( model_config = pydantic_settings.SettingsConfigDict( env_file=".env", - env_prefix=os.getenv(ENVIRONMENT_PREFIX, ""), + env_prefix=ENV_PREFIX, env_file_encoding="utf-8", populate_by_name=True, ) diff --git a/pyproject.toml b/pyproject.toml index e157fae..de924b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,6 +94,7 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.mypy] +plugins = ["pydantic.mypy"] files = ["microbootstrap", "tests"] python_version = "3.9" strict = true diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 0000000..2f4a7cb --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,42 @@ +import importlib +import typing + +import pytest + +import microbootstrap.settings + + +@pytest.fixture +def reset_reloaded_settings_module() -> typing.Iterator[None]: + yield + importlib.reload(microbootstrap.settings) + + +@pytest.mark.parametrize("alias", ["SERVICE_NAME", "MY_SERVICE_SERVICE_NAME"]) +def test_settings_service_name_aliases(monkeypatch: pytest.MonkeyPatch, alias: str) -> None: + monkeypatch.setenv("ENVIRONMENT_PREFIX", "MY_SERVICE_") + monkeypatch.setenv(alias, "my service") + importlib.reload(microbootstrap.settings) + + settings = microbootstrap.settings.BaseServiceSettings() + assert settings.service_name == "my service" + + +def test_settings_service_name_default() -> None: + settings = microbootstrap.settings.BaseServiceSettings() + assert settings.service_name == "micro-service" + + +@pytest.mark.parametrize("alias", ["CI_COMMIT_TAG", "MY_SERVICE_SERVICE_VERSION"]) +def test_settings_service_version_aliases(monkeypatch: pytest.MonkeyPatch, alias: str) -> None: + monkeypatch.setenv("ENVIRONMENT_PREFIX", "MY_SERVICE_") + monkeypatch.setenv(alias, "1.2.3") + importlib.reload(microbootstrap.settings) + + settings = microbootstrap.settings.BaseServiceSettings() + assert settings.service_version == "1.2.3" + + +def test_settings_service_version_default() -> None: + settings = microbootstrap.settings.BaseServiceSettings() + assert settings.service_version == "1.0.0" From 1a454f9551e85d9952f80e4291066da8d0c0c150 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Wed, 9 Oct 2024 14:42:05 +0300 Subject: [PATCH 2/7] Fix ruff diagnostic --- tests/test_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 2f4a7cb..d3e5735 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -7,7 +7,7 @@ @pytest.fixture -def reset_reloaded_settings_module() -> typing.Iterator[None]: +def _reset_reloaded_settings_module() -> typing.Iterator[None]: yield importlib.reload(microbootstrap.settings) From 18f2ab7d9a58a5d93ba906cc698ec83104acc557 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Wed, 9 Oct 2024 14:44:43 +0300 Subject: [PATCH 3/7] Update pre-commit dependencies --- .pre-commit-config.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f969be..70371b7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,13 @@ repos: - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.1 + rev: v1.11.2 hooks: - id: mypy name: mypy always_run: true + additional_dependencies: [pydantic>=2.3.4] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.0 + rev: v0.6.9 hooks: - id: ruff name: ruff-check From 6e305fb26f54af1bcc945ea4224d30d1ff959ffb Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Wed, 9 Oct 2024 14:49:17 +0300 Subject: [PATCH 4/7] Run ruff check --- tests/conftest.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e3cf0a3..d9249ac 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,47 +26,47 @@ def anyio_backend() -> str: return "asyncio" -@pytest.fixture() +@pytest.fixture def default_litestar_app() -> litestar.Litestar: return litestar.Litestar() -@pytest.fixture() +@pytest.fixture def minimal_sentry_config() -> SentryConfig: return SentryConfig(sentry_dsn="https://examplePublicKey@o0.ingest.sentry.io/0") -@pytest.fixture() +@pytest.fixture def minimal_logging_config() -> LoggingConfig: return LoggingConfig(service_debug=False) -@pytest.fixture() +@pytest.fixture def minimal_base_prometheus_config() -> BasePrometheusConfig: return BasePrometheusConfig() -@pytest.fixture() +@pytest.fixture def minimal_fastapi_prometheus_config() -> FastApiPrometheusConfig: return FastApiPrometheusConfig() -@pytest.fixture() +@pytest.fixture def minimal_litestar_prometheus_config() -> LitestarPrometheusConfig: return LitestarPrometheusConfig() -@pytest.fixture() +@pytest.fixture def minimal_swagger_config() -> SwaggerConfig: return SwaggerConfig() -@pytest.fixture() +@pytest.fixture def minimal_cors_config() -> SwaggerConfig: return CorsConfig(cors_allowed_origins=["*"]) -@pytest.fixture() +@pytest.fixture def minimal_opentelemetry_config() -> OpentelemetryConfig: return OpentelemetryConfig( service_name="test-micro-service", @@ -77,21 +77,21 @@ def minimal_opentelemetry_config() -> OpentelemetryConfig: ) -@pytest.fixture() +@pytest.fixture def base_settings() -> BaseServiceSettings: return BaseServiceSettings() -@pytest.fixture() +@pytest.fixture def magic_mock() -> MagicMock: return MagicMock() -@pytest.fixture() +@pytest.fixture def async_mock() -> AsyncMock: return AsyncMock() -@pytest.fixture() +@pytest.fixture def console_writer() -> ConsoleWriter: return ConsoleWriter(writer_enabled=False) From c450959b9f28268e3b93fcbe08a65db7055270a4 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Wed, 9 Oct 2024 14:52:34 +0300 Subject: [PATCH 5/7] Fix mypy issue --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index d9249ac..cab6f46 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -62,7 +62,7 @@ def minimal_swagger_config() -> SwaggerConfig: @pytest.fixture -def minimal_cors_config() -> SwaggerConfig: +def minimal_cors_config() -> CorsConfig: return CorsConfig(cors_allowed_origins=["*"]) From f4df1ef646b49f80ea237fdf1fde3db159f78016 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Wed, 9 Oct 2024 14:55:39 +0300 Subject: [PATCH 6/7] Fix mypy issue --- microbootstrap/instruments/prometheus_instrument.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/microbootstrap/instruments/prometheus_instrument.py b/microbootstrap/instruments/prometheus_instrument.py index 44e8e01..9c57cb2 100644 --- a/microbootstrap/instruments/prometheus_instrument.py +++ b/microbootstrap/instruments/prometheus_instrument.py @@ -36,5 +36,5 @@ def is_ready(self) -> bool: ) @classmethod - def get_config_type(cls) -> type[BasePrometheusConfig]: - return BasePrometheusConfig + def get_config_type(cls) -> type[PrometheusConfigT]: + return BasePrometheusConfig # type: ignore[return-value] From 9120ab72348f9b2b1ff628176ce6518d56449898 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 10 Oct 2024 11:40:03 +0300 Subject: [PATCH 7/7] Fix reset settings module fixture --- tests/conftest.py | 9 +++++++++ tests/test_settings.py | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index cab6f46..dbec5d5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,12 @@ from __future__ import annotations +import importlib +import typing from unittest.mock import AsyncMock, MagicMock import litestar import pytest +import microbootstrap.settings from microbootstrap import ( FastApiPrometheusConfig, LitestarPrometheusConfig, @@ -95,3 +98,9 @@ def async_mock() -> AsyncMock: @pytest.fixture def console_writer() -> ConsoleWriter: return ConsoleWriter(writer_enabled=False) + + +@pytest.fixture +def reset_reloaded_settings_module() -> typing.Iterator[None]: + yield + importlib.reload(microbootstrap.settings) diff --git a/tests/test_settings.py b/tests/test_settings.py index d3e5735..746c574 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,15 +1,11 @@ import importlib -import typing import pytest import microbootstrap.settings -@pytest.fixture -def _reset_reloaded_settings_module() -> typing.Iterator[None]: - yield - importlib.reload(microbootstrap.settings) +pytestmark = [pytest.mark.usefixtures("reset_reloaded_settings_module")] @pytest.mark.parametrize("alias", ["SERVICE_NAME", "MY_SERVICE_SERVICE_NAME"])