Repository: svaningelgem/logprise
Pull request #20: feat: Adding custom NotifyType parameter
Author: login: abhat-koppert
Created: 2025-04-23T19:23:24Z | Merged: 2025-04-25T15:33:30Z

Added the parameter for a custom NotifyParameter and a basic relevant test


Diff:
diff --git a/.gitignore b/.gitignore
index ff39f36..71e5a5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -174,3 +174,5 @@ cython_debug/
 .idea/
 *.iml
 .ruff_cache/
+
+.vscode/
diff --git a/logprise/__init__.py b/logprise/__init__.py
index 544aa02..b6e140f 100644
--- a/logprise/__init__.py
+++ b/logprise/__init__.py
@@ -12,6 +12,7 @@
 import apprise.cli
 import loguru
 import loguru._logger
+from apprise import NotifyType
 from apprise.common import NotifyFormat
 from loguru import logger
 
@@ -207,7 +208,10 @@ def accumulate_log(self, message: loguru.Message) -> None:
             self.buffer.append(message)
 
     def send_notification(
-        self, title: str = "Script Notifications", body_format: str | NotifyFormat = NotifyFormat.TEXT
+        self,
+        title: str = "Script Notifications",
+        notify_type: str | NotifyType = NotifyType.WARNING,
+        body_format: str | NotifyFormat = NotifyFormat.TEXT,
     ) -> None:
         """Send a single notification with all accumulated logs."""
         if not self.buffer:
@@ -215,7 +219,10 @@ def send_notification(
 
         # Format the buffered logs into a single message
         message = "".join(self.buffer).replace("\r", "")
-        if self.apprise_obj and self.apprise_obj.notify(title=title, body=message, body_format=body_format):
+
+        if self.apprise_obj and self.apprise_obj.notify(
+            title=title, notify_type=notify_type, body=message, body_format=body_format
+        ):
             self.buffer.clear()  # Clear the buffer after sending
 
 
diff --git a/logprise/__init__.pyi b/logprise/__init__.pyi
index b8fa7e6..5a16bd8 100644
--- a/logprise/__init__.pyi
+++ b/logprise/__init__.pyi
@@ -74,7 +74,12 @@ class Appriser:
     @notification_level.setter
     def notification_level(self, value: int | str | loguru.Level) -> None: ...
     def accumulate_log(self, message: loguru.Message) -> None: ...
-    def send_notification(self, title: str = "Script Notifications", body_format: str | NotifyFormat = ...) -> None: ...
+    def send_notification(
+        self,
+        title: str = "Script Notifications",
+        notify_type: str | apprise.NotifyType = ...,
+        body_format: str | NotifyFormat = ...,
+    ) -> None: ...
 
     if sys.version_info >= (3, 13):
         def __replace__(self, /, **changes: object) -> Appriser: ...
diff --git a/tests/test_logprise.py b/tests/test_logprise.py
index 56d3ea9..90e2830 100644
--- a/tests/test_logprise.py
+++ b/tests/test_logprise.py
@@ -2,7 +2,7 @@
 import re
 
 import pytest
-from apprise import NotifyFormat
+from apprise import NotifyFormat, NotifyType
 from loguru import logger
 
 from logprise import Appriser, InterceptHandler
@@ -237,6 +237,7 @@ def test_all_standard_levels():
 def test_send_notification_parameters(mocker, noop):
     test_message = "Test log message"
     custom_title = "Custom Title"
+    custom_type = "success"
     custom_format = NotifyFormat.MARKDOWN
 
     appriser = Appriser()
@@ -245,7 +246,49 @@ def test_send_notification_parameters(mocker, noop):
 
     mock_notify = mocker.patch.object(appriser.apprise_obj, "notify")
 
-    appriser.send_notification(title=custom_title, body_format=custom_format)
+    appriser.send_notification(title=custom_title, notify_type=custom_type, body_format=custom_format)
+
+    mock_notify.assert_called_once_with(
+        title=custom_title, notify_type=custom_type, body=test_message, body_format=custom_format
+    )
+    assert len(appriser.buffer) == 0
+
+
+@pytest.mark.parametrize(
+    "notify_type_param, notify_format_param",
+    [
+        # Using string values
+        ("info", "text"),
+        ("success", "markdown"),
+        ("warning", "html"),
+        ("failure", "text"),
+        # Using Apprise enum objects
+        (NotifyType.INFO, NotifyFormat.TEXT),
+        (NotifyType.SUCCESS, NotifyFormat.MARKDOWN),
+        (NotifyType.WARNING, NotifyFormat.HTML),
+        (NotifyType.FAILURE, NotifyFormat.TEXT),
+        # Mixed: string type with enum format and vice versa
+        ("info", NotifyFormat.HTML),
+        (NotifyType.SUCCESS, "markdown"),
+    ],
+)
+def test_notification_parameter_types(mocker, noop, notify_type_param, notify_format_param):
+    """Test that Appriser accepts different parameter types for notify_type and body_format"""
+    test_message = "Test log message"
+    custom_title = "Custom Title"
+
+    appriser = Appriser()
+    appriser.add(noop)
+    appriser.buffer.append(test_message)
+
+    mock_notify = mocker.patch.object(appriser.apprise_obj, "notify")
+
+    # Call with the parametrized values
+    appriser.send_notification(title=custom_title, notify_type=notify_type_param, body_format=notify_format_param)
+
+    # Verify the parameters were passed through correctly
+    mock_notify.assert_called_once_with(
+        title=custom_title, notify_type=notify_type_param, body=test_message, body_format=notify_format_param
+    )
 
-    mock_notify.assert_called_once_with(title=custom_title, body=test_message, body_format=custom_format)
     assert len(appriser.buffer) == 0


Reviews:
user: login: svaningelgem
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-24T04:12:31Z
user: login: svaningelgem
state: DISMISSED
author_association: OWNER
submitted_at: 2025-04-24T04:15:17Z
user: login: abhat-koppert
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T14:37:18Z
user: login: abhat-koppert
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T14:37:30Z
user: login: svaningelgem
state: APPROVED
author_association: OWNER
submitted_at: 2025-04-25T15:33:20Z

Review comments:
diff_hunk: @@ -207,15 +208,23 @@ def accumulate_log(self, message: loguru.Message) -> None:
             self.buffer.append(message)
 
     def send_notification(
-        self, title: str = "Script Notifications", body_format: str | NotifyFormat = NotifyFormat.TEXT
+        self,
+        title: str = "Script Notifications",
+        notify_type: str | NotifyType = NotifyType.WARNING,
+        body_format: str | NotifyFormat = NotifyFormat.TEXT,
+
path: logprise/__init__.py
user: login: svaningelgem
body: I don't know why the automated tests were not run, but maybe let ruff run on the code?
This is what I generally do: `ruff format . && ruff check .`

In any case, I think this empty line should go. But ruff should do that for you.
created_at: 2025-04-24T04:12:31Z
author_association: OWNER
diff_hunk: @@ -207,15 +208,23 @@ def accumulate_log(self, message: loguru.Message) -> None:
             self.buffer.append(message)
 
     def send_notification(
-        self, title: str = "Script Notifications", body_format: str | NotifyFormat = NotifyFormat.TEXT
+        self,
+        title: str = "Script Notifications",
+        notify_type: str | NotifyType = NotifyType.WARNING,
+        body_format: str | NotifyFormat = NotifyFormat.TEXT,
+
     ) -> None:
         """Send a single notification with all accumulated logs."""
         if not self.buffer:
             return
 
         # Format the buffered logs into a single message
         message = "".join(self.buffer).replace("\r", "")
-        if self.apprise_obj and self.apprise_obj.notify(title=title, body=message, body_format=body_format):
+
+        if self.apprise_obj and self.apprise_obj.notify(
+            title=title, notify_type=notify_type, body=message, body_format=body_format
+        ):
+
path: logprise/__init__.py
user: login: svaningelgem
body: Remove empty line
created_at: 2025-04-24T04:12:48Z
author_association: OWNER
diff_hunk: @@ -245,7 +247,53 @@ def test_send_notification_parameters(mocker, noop):
 
     mock_notify = mocker.patch.object(appriser.apprise_obj, "notify")
 
+    appriser.send_notification(title=custom_title, notify_type=custom_type, body_format=custom_format)
+
+    mock_notify.assert_called_once_with(
+        title=custom_title, notify_type=custom_type, body=test_message, body_format=custom_format
+    )
+    assert len(appriser.buffer) == 0
+
+
+@pytest.mark.parametrize(
+    "notify_type_param, notify_format_param",
+    [
+        # Using string values
+        ("info", "text"),
+        ("success", "markdown"),
+        ("warning", "html"),
+        ("failure", "text"),
+        # Using Apprise enum objects
+        (NotifyType.INFO, NotifyFormat.TEXT),
+        (NotifyType.SUCCESS, NotifyFormat.MARKDOWN),
+        (NotifyType.WARNING, NotifyFormat.HTML),
+        (NotifyType.FAILURE, NotifyFormat.TEXT),
+        # Mixed: string type with enum format and vice versa
+        ("info", NotifyFormat.HTML),
+        (NotifyType.SUCCESS, "markdown"),
+    ],
+)
+def test_notification_parameter_types(mocker, noop, notify_type_param, notify_format_param):
path: tests/test_logprise.py
user: login: svaningelgem
body: I tried to run the tests, but they seem to fail. Can you have a look at them?
created_at: 2025-04-24T04:15:09Z
author_association: OWNER
diff_hunk: @@ -207,15 +208,23 @@ def accumulate_log(self, message: loguru.Message) -> None:
             self.buffer.append(message)
 
     def send_notification(
-        self, title: str = "Script Notifications", body_format: str | NotifyFormat = NotifyFormat.TEXT
+        self,
+        title: str = "Script Notifications",
+        notify_type: str | NotifyType = NotifyType.WARNING,
+        body_format: str | NotifyFormat = NotifyFormat.TEXT,
+
path: logprise/__init__.py
user: login: abhat-koppert
body: Super weird. I use ruff as my main formatter in VS Code. I guess it missed something. Sorry about that. I have committed the latest change with the fix. Lmk if it is alright.
created_at: 2025-04-25T14:37:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -245,7 +247,53 @@ def test_send_notification_parameters(mocker, noop):
 
     mock_notify = mocker.patch.object(appriser.apprise_obj, "notify")
 
+    appriser.send_notification(title=custom_title, notify_type=custom_type, body_format=custom_format)
+
+    mock_notify.assert_called_once_with(
+        title=custom_title, notify_type=custom_type, body=test_message, body_format=custom_format
+    )
+    assert len(appriser.buffer) == 0
+
+
+@pytest.mark.parametrize(
+    "notify_type_param, notify_format_param",
+    [
+        # Using string values
+        ("info", "text"),
+        ("success", "markdown"),
+        ("warning", "html"),
+        ("failure", "text"),
+        # Using Apprise enum objects
+        (NotifyType.INFO, NotifyFormat.TEXT),
+        (NotifyType.SUCCESS, NotifyFormat.MARKDOWN),
+        (NotifyType.WARNING, NotifyFormat.HTML),
+        (NotifyType.FAILURE, NotifyFormat.TEXT),
+        # Mixed: string type with enum format and vice versa
+        ("info", NotifyFormat.HTML),
+        (NotifyType.SUCCESS, "markdown"),
+    ],
+)
+def test_notification_parameter_types(mocker, noop, notify_type_param, notify_format_param):
path: tests/test_logprise.py
user: login: abhat-koppert
body: It seems that I messed something up with the merge conflict resolution. I am not too familiar with GH's merge conflict resolution so I think that was the issue. Should be ok now
created_at: 2025-04-25T14:37:30Z
author_association: CONTRIBUTOR

PR comments:
user: login: svaningelgem
created_at: 2025-04-23T19:27:03Z
body: Hi, could you resolve the conflicts?
author_association: OWNER
user: login: svaningelgem
created_at: 2025-04-24T04:11:19Z
body: Could you also adjust the `pyi` file? And maybe there is a way to share information between these 2 as otherwise we're just repeating the same title in both files?
author_association: OWNER
user: login: codecov[bot]
created_at: 2025-04-25T14:34:40Z
body: ## [Codecov](https://app.codecov.io/gh/svaningelgem/logprise/pull/20?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Steven+Van+Ingelgem) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 100.00%. Comparing base [(`aa83725`)](https://app.codecov.io/gh/svaningelgem/logprise/commit/aa837254b88220cc220fefdbd6c7555273fb6cc7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Steven+Van+Ingelgem) to head [(`b855d6d`)](https://app.codecov.io/gh/svaningelgem/logprise/commit/b855d6d14597ab2ea9e282a86dc0de473efe3ece?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Steven+Van+Ingelgem).
> Report is 1 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff            @@
##            master       #20   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         1           
  Lines          127       128    +1     
  Branches        18        18           
=========================================
+ Hits           127       128    +1     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/svaningelgem/logprise/pull/20?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Steven+Van+Ingelgem).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Steven+Van+Ingelgem).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: svaningelgem
created_at: 2025-04-25T14:39:17Z
body: Thanks, can you still adjust the pyi-file? I'll see if I can add a check in the automated procedures to enforce consistency.
author_association: OWNER
user: login: svaningelgem
created_at: 2025-04-25T15:35:08Z
body: Thanks for your contribution. It has been merged now.
I also added the additional checks into the workflows.

Just let me know if you want to add more things or you prefer me to do a minor release now?
author_association: OWNER
user: login: abhat-koppert
created_at: 2025-04-25T15:48:41Z
body: A minor release would be nice for now.

 I am also running into an issue where I am attempting to send a message to slack via a Slack hook. However, it does not work when I do not use the `send_notification()` method. I have tried to force the flush interval to be much shorter than the predefined 1 hour. The only way the messages are sent is if I use the method mentioned above. 

I added the Slack hook via the `appriser.add()`. Should I have added it as one of the [apprise recommended config files](https://github.com/caronc/apprise/blob/master/apprise/cli.py) as you have mentioned in your README? Or is there something I am missing?

This is how my logger module is structured in the internal package I am building. Super basic, but ideally should get job done imo. The `logger` object exposed from this module should suffice in sending notifications to Slack when ```logger.error()``` is called, right? Or am I missing something?
```python
import os

from logprise import appriser, logger

appriser.add(
    servers=os.getenv("SLACKHOOK"),
)

appriser.flush_interval = 60

# Export logger and appriser for reuse
__all__ = ["logger", "appriser"]
```

author_association: CONTRIBUTOR