From fd3ae6090d7e18ca8c03a6a3125b877dd4e1b5a1 Mon Sep 17 00:00:00 2001 From: Peter Schutt Date: Mon, 16 Jan 2023 19:08:27 +1000 Subject: [PATCH] refactor: use constants for test/local env checks. We are starting to amass a bit of functionality that is condition upon the environment setting. E.g., sentry init disabled by default in test and local environments, alternate logging config if environment is local, and server reloading automatically configured for local environment. So, it makes sense to have a bit more structure around these checks. Closes #244 --- src/starlite_saqlalchemy/constants.py | 11 +++++++++++ src/starlite_saqlalchemy/init_plugin.py | 3 ++- src/starlite_saqlalchemy/log/__init__.py | 3 ++- src/starlite_saqlalchemy/scripts.py | 7 ++----- src/starlite_saqlalchemy/settings.py | 11 +++++++++++ src/starlite_saqlalchemy/utils.py | 5 +++++ tests/unit/test_init_plugin.py | 20 +++++++------------- tests/unit/test_scripts.py | 24 +++++++++++++++--------- 8 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 src/starlite_saqlalchemy/constants.py diff --git a/src/starlite_saqlalchemy/constants.py b/src/starlite_saqlalchemy/constants.py new file mode 100644 index 00000000..8a5e75d3 --- /dev/null +++ b/src/starlite_saqlalchemy/constants.py @@ -0,0 +1,11 @@ +"""Application constants.""" +from __future__ import annotations + +from starlite_saqlalchemy.settings import app +from starlite_saqlalchemy.utils import case_insensitive_string_compare + +IS_TEST_ENVIRONMENT = case_insensitive_string_compare(app.ENVIRONMENT, app.TEST_ENVIRONMENT_NAME) +"""Flag indicating if the application is running in a test environment.""" + +IS_LOCAL_ENVIRONMENT = case_insensitive_string_compare(app.ENVIRONMENT, app.LOCAL_ENVIRONMENT_NAME) +"""Flag indicating if application is running in local development mode.""" diff --git a/src/starlite_saqlalchemy/init_plugin.py b/src/starlite_saqlalchemy/init_plugin.py index 4f79b092..08d4a244 100644 --- a/src/starlite_saqlalchemy/init_plugin.py +++ b/src/starlite_saqlalchemy/init_plugin.py @@ -51,6 +51,7 @@ def example_handler() -> dict: settings, sqlalchemy_plugin, ) +from starlite_saqlalchemy.constants import IS_LOCAL_ENVIRONMENT, IS_TEST_ENVIRONMENT from starlite_saqlalchemy.exceptions import HealthCheckConfigurationError from starlite_saqlalchemy.health import ( AbstractHealthCheck, @@ -333,7 +334,7 @@ def configure_sentry(self, app_config: AppConfig) -> None: do_sentry = ( self.config.do_sentry if self.config.do_sentry is not None - else settings.app.ENVIRONMENT not in {"local", "test"} + else not (IS_LOCAL_ENVIRONMENT or IS_TEST_ENVIRONMENT) ) if do_sentry: app_config.on_startup.append(sentry.configure) diff --git a/src/starlite_saqlalchemy/log/__init__.py b/src/starlite_saqlalchemy/log/__init__.py index 680aedb6..06105afa 100644 --- a/src/starlite_saqlalchemy/log/__init__.py +++ b/src/starlite_saqlalchemy/log/__init__.py @@ -9,6 +9,7 @@ from starlite.config.logging import LoggingConfig from starlite_saqlalchemy import settings +from starlite_saqlalchemy.constants import IS_LOCAL_ENVIRONMENT from . import controller, worker from .utils import EventFilter, msgspec_json_renderer @@ -43,7 +44,7 @@ structlog.stdlib.ProcessorFormatter.remove_processors_meta, ] -if settings.app.ENVIRONMENT == "local": # pragma: no cover +if IS_LOCAL_ENVIRONMENT: # pragma: no cover LoggerFactory: Any = structlog.WriteLoggerFactory console_processor = structlog.dev.ConsoleRenderer(colors=True) default_processors.extend([console_processor]) diff --git a/src/starlite_saqlalchemy/scripts.py b/src/starlite_saqlalchemy/scripts.py index 076c8d27..326e084b 100644 --- a/src/starlite_saqlalchemy/scripts.py +++ b/src/starlite_saqlalchemy/scripts.py @@ -2,15 +2,12 @@ import uvicorn from starlite_saqlalchemy import settings +from starlite_saqlalchemy.constants import IS_LOCAL_ENVIRONMENT def determine_should_reload() -> bool: """Evaluate whether reloading should be enabled.""" - return ( - settings.server.RELOAD - if settings.server.RELOAD is not None - else settings.app.ENVIRONMENT == "local" - ) + return settings.server.RELOAD if settings.server.RELOAD is not None else IS_LOCAL_ENVIRONMENT def determine_reload_dirs(should_reload: bool) -> list[str] | None: diff --git a/src/starlite_saqlalchemy/settings.py b/src/starlite_saqlalchemy/settings.py index ca803ba6..b182a6d8 100644 --- a/src/starlite_saqlalchemy/settings.py +++ b/src/starlite_saqlalchemy/settings.py @@ -35,6 +35,17 @@ class Config: """Run `Starlite` with `debug=True`.""" ENVIRONMENT: str = "prod" """'dev', 'prod', etc.""" + TEST_ENVIRONMENT_NAME: str = "test" + """Value of ENVIRONMENT used to determine if running tests. + + This should be the value of `ENVIRONMENT` in `test.env`. + """ + LOCAL_ENVIRONMENT_NAME: str = "local" + """Value of ENVIRONMENT used to determine if running in local development + mode. + + This should be the value of `ENVIRONMENT` in your local `.env` file. + """ NAME: str = "my-starlite-saqlalchemy-app" """Application name.""" diff --git a/src/starlite_saqlalchemy/utils.py b/src/starlite_saqlalchemy/utils.py index c140ac36..d949f2dc 100644 --- a/src/starlite_saqlalchemy/utils.py +++ b/src/starlite_saqlalchemy/utils.py @@ -3,6 +3,11 @@ from typing import Any +def case_insensitive_string_compare(a: str, b: str, /) -> bool: + """Compare `a` and `b`, stripping whitespace and ignoring case.""" + return a.strip().lower() == b.strip().lower() + + def dataclass_as_dict_shallow(dataclass: Any, *, exclude_none: bool = False) -> dict[str, Any]: """Convert a dataclass to dict, without deepcopy.""" ret: dict[str, Any] = {} diff --git a/tests/unit/test_init_plugin.py b/tests/unit/test_init_plugin.py index 469ef0b0..d86ed868 100644 --- a/tests/unit/test_init_plugin.py +++ b/tests/unit/test_init_plugin.py @@ -8,8 +8,7 @@ from starlite import Starlite from starlite.cache import SimpleCacheBackend -from starlite_saqlalchemy import init_plugin, sentry, settings -from starlite_saqlalchemy.testing import modify_settings +from starlite_saqlalchemy import init_plugin, sentry if TYPE_CHECKING: from typing import Any @@ -86,17 +85,12 @@ def test_ensure_list(in_: Any, out: Any) -> None: @pytest.mark.parametrize( - ("env", "exp"), - [ - ("dev", True), - ("prod", True), - ("local", False), - ("test", False), - ], + ("env", "exp"), [("dev", True), ("prod", True), ("local", False), ("test", False)] ) -def test_sentry_environment_gate(env: str, exp: bool) -> None: +def test_sentry_environment_gate(env: str, exp: bool, monkeypatch: MonkeyPatch) -> None: """Test that the sentry integration is configured under different environment names.""" - with modify_settings((settings.app, {"ENVIRONMENT": env})): - app = Starlite(route_handlers=[], on_app_init=[init_plugin.ConfigureApp()]) - assert bool(sentry.configure in app.on_startup) is exp # noqa: SIM901 + monkeypatch.setattr(init_plugin, "IS_LOCAL_ENVIRONMENT", env == "local") + monkeypatch.setattr(init_plugin, "IS_TEST_ENVIRONMENT", env == "test") + app = Starlite(route_handlers=[], on_app_init=[init_plugin.ConfigureApp()]) + assert bool(sentry.configure in app.on_startup) is exp # noqa: SIM901 diff --git a/tests/unit/test_scripts.py b/tests/unit/test_scripts.py index 452e2911..bb950e57 100644 --- a/tests/unit/test_scripts.py +++ b/tests/unit/test_scripts.py @@ -1,27 +1,33 @@ """Tests for scripts.py.""" +from __future__ import annotations + +from typing import TYPE_CHECKING import pytest -from starlite_saqlalchemy import settings -from starlite_saqlalchemy.scripts import determine_reload_dirs, determine_should_reload +from starlite_saqlalchemy import scripts, settings from starlite_saqlalchemy.testing import modify_settings +if TYPE_CHECKING: + from pytest import MonkeyPatch + @pytest.mark.parametrize(("reload", "expected"), [(None, True), (True, True), (False, False)]) -def test_uvicorn_config_auto_reload_local(reload: bool | None, expected: bool) -> None: +def test_uvicorn_config_auto_reload_local( + reload: bool | None, expected: bool, monkeypatch: MonkeyPatch +) -> None: """Test that setting ENVIRONMENT to 'local' triggers auto reload.""" - with modify_settings( - (settings.app, {"ENVIRONMENT": "local"}), (settings.server, {"RELOAD": reload}) - ): - assert determine_should_reload() is expected + monkeypatch.setattr(scripts, "IS_LOCAL_ENVIRONMENT", True) + with modify_settings((settings.server, {"RELOAD": reload})): + assert scripts.determine_should_reload() is expected @pytest.mark.parametrize("reload", [True, False]) def test_uvicorn_config_reload_dirs(reload: bool) -> None: """Test that RELOAD_DIRS is only used when RELOAD is enabled.""" if not reload: - assert determine_reload_dirs(reload) is None + assert scripts.determine_reload_dirs(reload) is None else: - reload_dirs = determine_reload_dirs(reload) + reload_dirs = scripts.determine_reload_dirs(reload) assert reload_dirs is not None assert reload_dirs == settings.server.RELOAD_DIRS