From 12ff53ab9c7bda86b8dda03cd1e7e00d3dc71ce8 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Sat, 22 Mar 2025 08:33:12 +0300 Subject: [PATCH] rename bootstrap to bootstrapper, refactor --- lite_bootstrap/__init__.py | 38 +++++++++++++++++++ .../{bootstraps => bootstrappers}/__init__.py | 0 .../{bootstraps => bootstrappers}/base.py | 16 +++++--- .../fastapi_bootstrapper.py} | 9 +++-- .../free_bootstrapper.py} | 9 +++-- .../litestar_bootstrapper.py} | 9 +++-- lite_bootstrap/instruments/base.py | 6 +-- .../instruments/logging_instrument.py | 6 +-- .../instruments/opentelemetry_instrument.py | 6 +-- .../instruments/sentry_instrument.py | 6 +-- lite_bootstrap/types.py | 1 + tests/test_fastapi_bootstrap.py | 12 +++--- tests/test_free_bootstrap.py | 11 ++++-- tests/test_litestar_bootstrap.py | 14 +++---- 14 files changed, 98 insertions(+), 45 deletions(-) rename lite_bootstrap/{bootstraps => bootstrappers}/__init__.py (100%) rename lite_bootstrap/{bootstraps => bootstrappers}/base.py (55%) rename lite_bootstrap/{bootstraps/fastapi_bootstrap.py => bootstrappers/fastapi_bootstrapper.py} (90%) rename lite_bootstrap/{bootstraps/free_bootstrap.py => bootstrappers/free_bootstrapper.py} (69%) rename lite_bootstrap/{bootstraps/litestar_bootstrap.py => bootstrappers/litestar_bootstrapper.py} (90%) diff --git a/lite_bootstrap/__init__.py b/lite_bootstrap/__init__.py index e69de29..bb1cff1 100644 --- a/lite_bootstrap/__init__.py +++ b/lite_bootstrap/__init__.py @@ -0,0 +1,38 @@ +from lite_bootstrap.bootstrappers.fastapi_bootstrapper import ( + FastAPIBootstrapper, + FastAPIHealthChecksInstrument, + FastAPILoggingInstrument, + FastAPIOpenTelemetryInstrument, + FastAPISentryInstrument, +) +from lite_bootstrap.bootstrappers.free_bootstrapper import FreeBootstrapper +from lite_bootstrap.bootstrappers.litestar_bootstrapper import ( + LitestarBootstrapper, + LitestarHealthChecksInstrument, + LitestarLoggingInstrument, + LitestarOpenTelemetryInstrument, + LitestarSentryInstrument, +) +from lite_bootstrap.instruments.healthchecks_instrument import HealthChecksInstrument +from lite_bootstrap.instruments.logging_instrument import LoggingInstrument +from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument +from lite_bootstrap.instruments.sentry_instrument import SentryInstrument + + +__all__ = [ + "FastAPIBootstrapper", + "FastAPIHealthChecksInstrument", + "FastAPILoggingInstrument", + "FastAPIOpenTelemetryInstrument", + "FastAPISentryInstrument", + "FreeBootstrapper", + "HealthChecksInstrument", + "LitestarBootstrapper", + "LitestarHealthChecksInstrument", + "LitestarLoggingInstrument", + "LitestarOpenTelemetryInstrument", + "LitestarSentryInstrument", + "LoggingInstrument", + "OpenTelemetryInstrument", + "SentryInstrument", +] diff --git a/lite_bootstrap/bootstraps/__init__.py b/lite_bootstrap/bootstrappers/__init__.py similarity index 100% rename from lite_bootstrap/bootstraps/__init__.py rename to lite_bootstrap/bootstrappers/__init__.py diff --git a/lite_bootstrap/bootstraps/base.py b/lite_bootstrap/bootstrappers/base.py similarity index 55% rename from lite_bootstrap/bootstraps/base.py rename to lite_bootstrap/bootstrappers/base.py index fe8a37f..727c56d 100644 --- a/lite_bootstrap/bootstraps/base.py +++ b/lite_bootstrap/bootstrappers/base.py @@ -3,20 +3,24 @@ from lite_bootstrap.instruments.base import BaseInstrument from lite_bootstrap.service_config import ServiceConfig -from lite_bootstrap.types import ApplicationT +from lite_bootstrap.types import ApplicationT, BootstrapObjectT -class BaseBootstrap(abc.ABC, typing.Generic[ApplicationT]): - application: ApplicationT +class BaseBootstrapper(abc.ABC, typing.Generic[BootstrapObjectT, ApplicationT]): + bootstrap_object: BootstrapObjectT instruments: typing.Sequence[BaseInstrument] service_config: ServiceConfig - def bootstrap(self) -> None: + @abc.abstractmethod + def _prepare_application(self) -> ApplicationT: ... + + def bootstrap(self) -> ApplicationT: for one_instrument in self.instruments: if one_instrument.is_ready(self.service_config): - one_instrument.bootstrap(self.service_config, self.application) + one_instrument.bootstrap(self.service_config, self.bootstrap_object) + return self._prepare_application() def teardown(self) -> None: for one_instrument in self.instruments: if one_instrument.is_ready(self.service_config): - one_instrument.teardown(self.application) + one_instrument.teardown(self.bootstrap_object) diff --git a/lite_bootstrap/bootstraps/fastapi_bootstrap.py b/lite_bootstrap/bootstrappers/fastapi_bootstrapper.py similarity index 90% rename from lite_bootstrap/bootstraps/fastapi_bootstrap.py rename to lite_bootstrap/bootstrappers/fastapi_bootstrapper.py index 5136821..cfc15f8 100644 --- a/lite_bootstrap/bootstraps/fastapi_bootstrap.py +++ b/lite_bootstrap/bootstrappers/fastapi_bootstrapper.py @@ -2,7 +2,7 @@ import dataclasses import typing -from lite_bootstrap.bootstraps.base import BaseBootstrap +from lite_bootstrap.bootstrappers.base import BaseBootstrapper from lite_bootstrap.instruments.healthchecks_instrument import HealthChecksInstrument, HealthCheckTypedDict from lite_bootstrap.instruments.logging_instrument import LoggingInstrument from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument @@ -66,8 +66,8 @@ class FastAPISentryInstrument(SentryInstrument): ... @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) -class FastAPIBootstrap(BaseBootstrap[fastapi.FastAPI]): - application: fastapi.FastAPI +class FastAPIBootstrapper(BaseBootstrapper[fastapi.FastAPI, fastapi.FastAPI]): + bootstrap_object: fastapi.FastAPI instruments: typing.Sequence[ FastAPIOpenTelemetryInstrument | FastAPISentryInstrument @@ -75,3 +75,6 @@ class FastAPIBootstrap(BaseBootstrap[fastapi.FastAPI]): | FastAPILoggingInstrument ] service_config: ServiceConfig + + def _prepare_application(self) -> fastapi.FastAPI: + return self.bootstrap_object diff --git a/lite_bootstrap/bootstraps/free_bootstrap.py b/lite_bootstrap/bootstrappers/free_bootstrapper.py similarity index 69% rename from lite_bootstrap/bootstraps/free_bootstrap.py rename to lite_bootstrap/bootstrappers/free_bootstrapper.py index 7f79e67..abbbd72 100644 --- a/lite_bootstrap/bootstraps/free_bootstrap.py +++ b/lite_bootstrap/bootstrappers/free_bootstrapper.py @@ -1,7 +1,7 @@ import dataclasses import typing -from lite_bootstrap.bootstraps.base import BaseBootstrap +from lite_bootstrap.bootstrappers.base import BaseBootstrapper from lite_bootstrap.instruments.logging_instrument import LoggingInstrument from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument from lite_bootstrap.instruments.sentry_instrument import SentryInstrument @@ -9,7 +9,10 @@ @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) -class FreeBootstrap(BaseBootstrap[None]): - application: None = None +class FreeBootstrapper(BaseBootstrapper[None, None]): + bootstrap_object: None = None instruments: typing.Sequence[OpenTelemetryInstrument | SentryInstrument | LoggingInstrument] service_config: ServiceConfig + + def _prepare_application(self) -> None: + return self.bootstrap_object diff --git a/lite_bootstrap/bootstraps/litestar_bootstrap.py b/lite_bootstrap/bootstrappers/litestar_bootstrapper.py similarity index 90% rename from lite_bootstrap/bootstraps/litestar_bootstrap.py rename to lite_bootstrap/bootstrappers/litestar_bootstrapper.py index 8ce5cae..5c97746 100644 --- a/lite_bootstrap/bootstraps/litestar_bootstrap.py +++ b/lite_bootstrap/bootstrappers/litestar_bootstrapper.py @@ -2,7 +2,7 @@ import dataclasses import typing -from lite_bootstrap.bootstraps.base import BaseBootstrap +from lite_bootstrap.bootstrappers.base import BaseBootstrapper from lite_bootstrap.instruments.healthchecks_instrument import HealthChecksInstrument, HealthCheckTypedDict from lite_bootstrap.instruments.logging_instrument import LoggingInstrument from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument @@ -64,8 +64,8 @@ class LitestarSentryInstrument(SentryInstrument): ... @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) -class LitestarBootstrap(BaseBootstrap[AppConfig]): - application: AppConfig +class LitestarBootstrapper(BaseBootstrapper[AppConfig, litestar.Litestar]): + bootstrap_object: AppConfig instruments: typing.Sequence[ LitestarOpenTelemetryInstrument | LitestarSentryInstrument @@ -73,3 +73,6 @@ class LitestarBootstrap(BaseBootstrap[AppConfig]): | LitestarLoggingInstrument ] service_config: ServiceConfig + + def _prepare_application(self) -> litestar.Litestar: + return litestar.Litestar.from_config(self.bootstrap_object) diff --git a/lite_bootstrap/instruments/base.py b/lite_bootstrap/instruments/base.py index 01462a2..0d5cbf9 100644 --- a/lite_bootstrap/instruments/base.py +++ b/lite_bootstrap/instruments/base.py @@ -1,13 +1,13 @@ import abc from lite_bootstrap.service_config import ServiceConfig -from lite_bootstrap.types import ApplicationT +from lite_bootstrap.types import BootstrapObjectT class BaseInstrument(abc.ABC): - def bootstrap(self, service_config: ServiceConfig, application: ApplicationT | None = None) -> None: ... # noqa: B027 + def bootstrap(self, service_config: ServiceConfig, bootstrap_object: BootstrapObjectT | None = None) -> None: ... # noqa: B027 - def teardown(self, application: ApplicationT | None = None) -> None: ... # noqa: B027 + def teardown(self, bootstrap_object: BootstrapObjectT | None = None) -> None: ... # noqa: B027 @abc.abstractmethod def is_ready(self, service_config: ServiceConfig) -> bool: ... diff --git a/lite_bootstrap/instruments/logging_instrument.py b/lite_bootstrap/instruments/logging_instrument.py index 2919e3a..c87e458 100644 --- a/lite_bootstrap/instruments/logging_instrument.py +++ b/lite_bootstrap/instruments/logging_instrument.py @@ -6,7 +6,7 @@ from lite_bootstrap.instruments.base import BaseInstrument from lite_bootstrap.service_config import ServiceConfig -from lite_bootstrap.types import ApplicationT +from lite_bootstrap.types import BootstrapObjectT if typing.TYPE_CHECKING: @@ -109,7 +109,7 @@ class LoggingInstrument(BaseInstrument): def is_ready(self, service_config: ServiceConfig) -> bool: return not service_config.service_debug - def bootstrap(self, _: ServiceConfig, __: ApplicationT | None = None) -> None: + def bootstrap(self, _: ServiceConfig, __: BootstrapObjectT | None = None) -> None: for unset_handlers_logger in self.logging_unset_handlers: logging.getLogger(unset_handlers_logger).handlers = [] @@ -129,5 +129,5 @@ def bootstrap(self, _: ServiceConfig, __: ApplicationT | None = None) -> None: cache_logger_on_first_use=True, ) - def teardown(self, _: ApplicationT | None = None) -> None: + def teardown(self, _: BootstrapObjectT | None = None) -> None: structlog.reset_defaults() diff --git a/lite_bootstrap/instruments/opentelemetry_instrument.py b/lite_bootstrap/instruments/opentelemetry_instrument.py index 36b781b..853ab62 100644 --- a/lite_bootstrap/instruments/opentelemetry_instrument.py +++ b/lite_bootstrap/instruments/opentelemetry_instrument.py @@ -6,7 +6,7 @@ from lite_bootstrap.instruments.base import BaseInstrument from lite_bootstrap.service_config import ServiceConfig -from lite_bootstrap.types import ApplicationT +from lite_bootstrap.types import BootstrapObjectT with contextlib.suppress(ImportError): @@ -35,7 +35,7 @@ class OpenTelemetryInstrument(BaseInstrument): def is_ready(self, _: ServiceConfig) -> bool: return bool(self.endpoint) - def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None) -> None: + def bootstrap(self, service_config: ServiceConfig, _: BootstrapObjectT | None = None) -> None: attributes = { resources.SERVICE_NAME: service_config.service_name, resources.TELEMETRY_SDK_LANGUAGE: "python", @@ -66,7 +66,7 @@ def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None one_instrumentor.instrument(tracer_provider=tracer_provider) set_tracer_provider(tracer_provider) - def teardown(self, _: ApplicationT | None = None) -> None: + def teardown(self, _: BootstrapObjectT | None = None) -> None: for one_instrumentor in self.instrumentors: if isinstance(one_instrumentor, InstrumentorWithParams): one_instrumentor.instrumentor.uninstrument(**one_instrumentor.additional_params) diff --git a/lite_bootstrap/instruments/sentry_instrument.py b/lite_bootstrap/instruments/sentry_instrument.py index 4660b18..5e0bd38 100644 --- a/lite_bootstrap/instruments/sentry_instrument.py +++ b/lite_bootstrap/instruments/sentry_instrument.py @@ -4,7 +4,7 @@ from lite_bootstrap.instruments.base import BaseInstrument from lite_bootstrap.service_config import ServiceConfig -from lite_bootstrap.types import ApplicationT +from lite_bootstrap.types import BootstrapObjectT with contextlib.suppress(ImportError): @@ -27,7 +27,7 @@ class SentryInstrument(BaseInstrument): def is_ready(self, _: ServiceConfig) -> bool: return bool(self.dsn) - def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None) -> None: + def bootstrap(self, service_config: ServiceConfig, _: BootstrapObjectT | None = None) -> None: sentry_sdk.init( dsn=self.dsn, sample_rate=self.sample_rate, @@ -42,4 +42,4 @@ def bootstrap(self, service_config: ServiceConfig, _: ApplicationT | None = None tags: dict[str, str] = self.tags or {} sentry_sdk.set_tags(tags) - def teardown(self, application: ApplicationT | None = None) -> None: ... + def teardown(self, bootstrap_object: BootstrapObjectT | None = None) -> None: ... diff --git a/lite_bootstrap/types.py b/lite_bootstrap/types.py index b66f777..19ebd88 100644 --- a/lite_bootstrap/types.py +++ b/lite_bootstrap/types.py @@ -1,4 +1,5 @@ import typing +BootstrapObjectT = typing.TypeVar("BootstrapObjectT", bound=typing.Any) ApplicationT = typing.TypeVar("ApplicationT", bound=typing.Any) diff --git a/tests/test_fastapi_bootstrap.py b/tests/test_fastapi_bootstrap.py index c45a5fb..be4f4fb 100644 --- a/tests/test_fastapi_bootstrap.py +++ b/tests/test_fastapi_bootstrap.py @@ -4,8 +4,8 @@ from starlette import status from starlette.testclient import TestClient -from lite_bootstrap.bootstraps.fastapi_bootstrap import ( - FastAPIBootstrap, +from lite_bootstrap.bootstrappers.fastapi_bootstrapper import ( + FastAPIBootstrapper, FastAPIHealthChecksInstrument, FastAPILoggingInstrument, FastAPIOpenTelemetryInstrument, @@ -19,8 +19,8 @@ def test_fastapi_bootstrap(fastapi_app: FastAPI, service_config: ServiceConfig) -> None: - fastapi_bootstrap = FastAPIBootstrap( - application=fastapi_app, + bootstrapper = FastAPIBootstrapper( + bootstrap_object=fastapi_app, service_config=service_config, instruments=[ FastAPIOpenTelemetryInstrument( @@ -37,7 +37,7 @@ def test_fastapi_bootstrap(fastapi_app: FastAPI, service_config: ServiceConfig) FastAPILoggingInstrument(logging_buffer_capacity=0), ], ) - fastapi_bootstrap.bootstrap() + bootstrapper.bootstrap() logger.info("testing logging", key="value") try: @@ -45,4 +45,4 @@ def test_fastapi_bootstrap(fastapi_app: FastAPI, service_config: ServiceConfig) assert response.status_code == status.HTTP_200_OK assert response.json() == {"health_status": True, "service_name": "microservice", "service_version": "2.0.0"} finally: - fastapi_bootstrap.teardown() + bootstrapper.teardown() diff --git a/tests/test_free_bootstrap.py b/tests/test_free_bootstrap.py index 391d109..1eb4a92 100644 --- a/tests/test_free_bootstrap.py +++ b/tests/test_free_bootstrap.py @@ -1,7 +1,7 @@ import structlog from opentelemetry.sdk.trace.export import ConsoleSpanExporter -from lite_bootstrap.bootstraps.free_bootstrap import FreeBootstrap +from lite_bootstrap.bootstrappers.free_bootstrapper import FreeBootstrapper from lite_bootstrap.instruments.logging_instrument import LoggingInstrument from lite_bootstrap.instruments.opentelemetry_instrument import OpenTelemetryInstrument from lite_bootstrap.instruments.sentry_instrument import SentryInstrument @@ -13,7 +13,7 @@ def test_free_bootstrap(service_config: ServiceConfig) -> None: - free_bootstrap = FreeBootstrap( + bootstrapper = FreeBootstrapper( service_config=service_config, instruments=[ OpenTelemetryInstrument( @@ -27,5 +27,8 @@ def test_free_bootstrap(service_config: ServiceConfig) -> None: LoggingInstrument(logging_buffer_capacity=0), ], ) - free_bootstrap.bootstrap() - logger.info("testing logging", key="value") + bootstrapper.bootstrap() + try: + logger.info("testing logging", key="value") + finally: + bootstrapper.teardown() diff --git a/tests/test_litestar_bootstrap.py b/tests/test_litestar_bootstrap.py index 701cd35..1093dcd 100644 --- a/tests/test_litestar_bootstrap.py +++ b/tests/test_litestar_bootstrap.py @@ -1,12 +1,11 @@ -import litestar import structlog from litestar import status_codes from litestar.config.app import AppConfig from litestar.testing import TestClient from opentelemetry.sdk.trace.export import ConsoleSpanExporter -from lite_bootstrap.bootstraps.litestar_bootstrap import ( - LitestarBootstrap, +from lite_bootstrap.bootstrappers.litestar_bootstrapper import ( + LitestarBootstrapper, LitestarHealthChecksInstrument, LitestarLoggingInstrument, LitestarOpenTelemetryInstrument, @@ -21,8 +20,8 @@ def test_litestar_bootstrap(service_config: ServiceConfig) -> None: app_config = AppConfig() - litestar_bootstrap = LitestarBootstrap( - application=app_config, + bootstrapper = LitestarBootstrapper( + bootstrap_object=app_config, service_config=service_config, instruments=[ LitestarOpenTelemetryInstrument( @@ -39,8 +38,7 @@ def test_litestar_bootstrap(service_config: ServiceConfig) -> None: LitestarLoggingInstrument(logging_buffer_capacity=0), ], ) - litestar_bootstrap.bootstrap() - application = litestar.Litestar.from_config(app_config) + application = bootstrapper.bootstrap() logger.info("testing logging", key="value") try: @@ -53,4 +51,4 @@ def test_litestar_bootstrap(service_config: ServiceConfig) -> None: "service_version": "2.0.0", } finally: - litestar_bootstrap.teardown() + bootstrapper.teardown()