Repository: mercadona/rele

Issue:
Rename post_publish hook to post_publish_success
We want to be more explicit with this middleware hook, just like we do with`post_process_message_failure` and `post_process_message_success`. 
For backwards compatibility we'll Initially allow both `post_publish` and `post_publish_success` and eventually we'll deprecate `post_publish`.

Discussion:

Patch:
diff --git a/rele/client.py b/rele/client.py
index 8ba1be1..bcb3af5 100644
--- a/rele/client.py
+++ b/rele/client.py
@@ -167,6 +167,9 @@ class Publisher:
             if raise_exception:
                 raise e
         else:
+            run_middleware_hook("post_publish_success", topic)
+
+            # DEPRECATED
             run_middleware_hook("post_publish", topic)
 
         return future
diff --git a/rele/middleware.py b/rele/middleware.py
index 84fb8da..dceb84d 100644
--- a/rele/middleware.py
+++ b/rele/middleware.py
@@ -1,4 +1,5 @@
 import importlib
+import warnings
 
 _middlewares = []
 
@@ -24,7 +25,20 @@ def run_middleware_hook(hook_name, *args, **kwargs):
         getattr(middleware, hook_name)(*args, **kwargs)
 
 
-class BaseMiddleware:
+class WarnDeprecatedHooks(type):
+    def __new__(cls, *args, **kwargs):
+        x = super().__new__(cls, *args, **kwargs)
+        if hasattr(x, "post_publish"):
+            warnings.warn(
+                "The post_publish hook in the middleware is deprecated "
+                "and will be removed in future versions. Please substitute it with "
+                "the post_publish_success hook instead.",
+                DeprecationWarning,
+            )
+        return x
+
+
+class BaseMiddleware(metaclass=WarnDeprecatedHooks):
     """Base class for middleware.  The default implementations
     for all hooks are no-ops and subclasses may implement whatever
     subset of hooks they like.
@@ -43,6 +57,11 @@ class BaseMiddleware:
         """
 
     def post_publish(self, topic):
+        """DEPRECATED: Called after Publisher sends message.
+        :param topic:
+        """
+
+    def post_publish_success(self, topic):
         """Called after Publisher sends message.
         :param topic:
         """
diff --git a/rele/publishing.py b/rele/publishing.py
index e2bf1d4..3368548 100644
--- a/rele/publishing.py
+++ b/rele/publishing.py
@@ -1,3 +1,5 @@
+from rele import config, discover
+
 from .client import Publisher
 
 _publisher = None
@@ -41,5 +43,10 @@ def publish(topic, data, **kwargs):
     :return: None
     """
     if not _publisher:
-        raise ValueError("init_global_publisher must be called first.")
+        settings, _ = discover.sub_modules()
+        if not hasattr(settings, "RELE"):
+            raise ValueError("Config setup not called and settings module not found.")
+
+        config.setup(settings.RELE)
+
     _publisher.publish(topic, data, **kwargs)


Test patch:
diff --git a/tests/test_middleware.py b/tests/test_middleware.py
index b13364d..57037bc 100644
--- a/tests/test_middleware.py
+++ b/tests/test_middleware.py
@@ -3,6 +3,7 @@ from unittest.mock import patch
 import pytest
 
 import rele
+from rele.middleware import BaseMiddleware
 
 
 class TestMiddleware:
@@ -23,3 +24,11 @@ class TestMiddleware:
         rele.setup(settings, foo="bar")
         assert mock_middleware_setup.called
         assert mock_middleware_setup.call_args_list[0][-1] == {"foo": "bar"}
+
+    def test_warns_about_deprecated_hooks(self):
+
+        with pytest.warns(DeprecationWarning):
+
+            class TestMiddleware(BaseMiddleware):
+                def post_publish(self, topic):
+                    pass
diff --git a/tests/test_publishing.py b/tests/test_publishing.py
index b8bc32f..4c7d4f8 100644
--- a/tests/test_publishing.py
+++ b/tests/test_publishing.py
@@ -1,12 +1,28 @@
 from unittest.mock import MagicMock, patch
 
 import pytest
+from tests import settings
 
 from rele import Publisher, publishing
 
 
 class TestPublish:
-    def test_raises_when_global_publisher_does_not_exist(self):
+    @patch("rele.publishing.Publisher", autospec=True)
+    def test_instantiates_publisher_and_publishes_when_does_not_exist(
+        self, mock_publisher
+    ):
+        with patch("rele.publishing.discover") as mock_discover:
+            mock_discover.sub_modules.return_value = settings, []
+
+            message = {"foo": "bar"}
+            publishing.publish(topic="order-cancelled", data=message, myattr="hello")
+
+            mock_publisher.return_value.publish.assert_called_with(
+                "order-cancelled", {"foo": "bar"}, myattr="hello"
+            )
+
+    def test_raises_error_when_publisher_does_not_exists_and_settings_not_found(self):
+        publishing._publisher = None
         message = {"foo": "bar"}
 
         with pytest.raises(ValueError):
@@ -18,6 +34,7 @@ class TestInitGlobalPublisher:
     def test_creates_global_publisher_when_published_called(
         self, mock_publisher, config
     ):
+        publishing._publisher = None
         mock_publisher.return_value = MagicMock(spec=Publisher)
         publishing.init_global_publisher(config)
         message = {"foo": "bar"}