diff --git a/src/lasuite/marketing/__init__.py b/src/lasuite/marketing/__init__.py index f507537..e24f6c2 100644 --- a/src/lasuite/marketing/__init__.py +++ b/src/lasuite/marketing/__init__.py @@ -1 +1,17 @@ """Marketing module.""" + +from django.utils.functional import LazyObject + +from .handler import MarketingHandler + + +class DefaultMarketing(LazyObject): + """Lazy object to handle the marketing backend.""" + + def _setup(self): + """Configure the marketing backend.""" + self._wrapped = marketing_handler() + + +marketing_handler = MarketingHandler() +marketing = DefaultMarketing() diff --git a/src/lasuite/marketing/exceptions.py b/src/lasuite/marketing/exceptions.py new file mode 100644 index 0000000..91da034 --- /dev/null +++ b/src/lasuite/marketing/exceptions.py @@ -0,0 +1,13 @@ +"""Marketing exceptions module.""" + + +class MarketingError(Exception): + """Base exception for all marketing exceptions.""" + + +class MarketingInvalidBackendError(MarketingError): + """Exception raised when the backend is invalid.""" + + +class ContactCreationError(MarketingError): + """Exception raised when the contact creation fails.""" diff --git a/src/lasuite/marketing/handler.py b/src/lasuite/marketing/handler.py new file mode 100644 index 0000000..3e32a26 --- /dev/null +++ b/src/lasuite/marketing/handler.py @@ -0,0 +1,46 @@ +"""marketing backendhandler.""" + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.utils.functional import cached_property +from django.utils.module_loading import import_string + +from lasuite.marketing.exceptions import MarketingInvalidBackendError + + +class MarketingHandler: + """Marketing handler managing the backend instantiation.""" + + def __init__(self, backend=None): + """Initialize the marketing handler.""" + # backend is an optional dict of marketing backend definitions + # (structured like settings.LASUITE_MARKETING). + self._backend = backend + self._marketing = None + + @cached_property + def backend(self): + """Put in cache the backend properties from the settings.""" + if self._backend is None: + try: + self._backend = settings.LASUITE_MARKETING.copy() + except AttributeError as e: + raise ImproperlyConfigured("settings.LASUITE_MARKETING is not configured") from e + return self._backend + + def __call__(self): + """Create if not existing the backend and then return it.""" + if self._marketing is None: + self._marketing = self.create_marketing(self.backend) + return self._marketing + + def create_marketing(self, params): + """Instantiate and configure the marketing backend.""" + params = params.copy() + backend = params.pop("BACKEND") + parameters = params.pop("PARAMETERS", {}) + try: + klass = import_string(backend) + except ImportError as e: + raise MarketingInvalidBackendError(f"Could not find backend {backend!r}: {e}") from e + return klass(**parameters) diff --git a/tests/marketing/__init__.py b/tests/marketing/__init__.py new file mode 100644 index 0000000..6cc1f54 --- /dev/null +++ b/tests/marketing/__init__.py @@ -0,0 +1 @@ +"""Marketing tests module.""" \ No newline at end of file diff --git a/tests/marketing/test_handler.py b/tests/marketing/test_handler.py new file mode 100644 index 0000000..75aeaa4 --- /dev/null +++ b/tests/marketing/test_handler.py @@ -0,0 +1,34 @@ +"""Test the marketing handler.""" + +import pytest +from django.core.exceptions import ImproperlyConfigured + +from lasuite.marketing.backends.dummy import DummyBackend +from lasuite.marketing.handler import MarketingHandler + + +def test_marketing_handler_from_settings(settings): + """Test the marketing handler from the settings.""" + settings.LASUITE_MARKETING = { + "BACKEND": "lasuite.marketing.backends.dummy.DummyBackend", + } + handler = MarketingHandler() + assert isinstance(handler(), DummyBackend) + + +def test_marketing_handler_from_backend(): + """Test the marketing handler from the backend.""" + handler = MarketingHandler( + backend={ + "BACKEND": "lasuite.marketing.backends.dummy.DummyBackend", + } + ) + assert isinstance(handler(), DummyBackend) + + +def test_marketing_backend_no_config(settings): + """Test the marketing handler when no config set should raise an error.""" + settings.LASUITE_MARKETING = None + handler = MarketingHandler() + with pytest.raises(ImproperlyConfigured): + handler() diff --git a/tests/marketing/test_marketing_detection_lazy_handler.py b/tests/marketing/test_marketing_detection_lazy_handler.py new file mode 100644 index 0000000..6910222 --- /dev/null +++ b/tests/marketing/test_marketing_detection_lazy_handler.py @@ -0,0 +1,12 @@ +"""Test the marketing lazy handler.""" + +from lasuite.marketing import marketing +from lasuite.marketing.backends.dummy import DummyBackend + + +def test_marketing_lazy_handler(settings): + """Test the marketing lazy handler.""" + settings.LASUITE_MARKETING = { + "BACKEND": "lasuite.marketing.backends.dummy.DummyBackend", + } + assert isinstance(marketing, DummyBackend)