python-ntfy 0.8.1__tar.gz → 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-ntfy
3
- Version: 0.8.1
4
- Summary: An ntfy library aiming for feature completeness
3
+ Version: 0.9.1
4
+ Summary: An easy-to-use library for the ntfy notification service.
5
5
  Keywords: ntfy,notifications,push,http,api
6
6
  Author: Matthew Cane
7
7
  Author-email: Matthew Cane <matthew.cane0@gmail.com>
@@ -18,32 +18,18 @@ Classifier: Topic :: Communications
18
18
  Classifier: Topic :: Internet :: WWW/HTTP
19
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Requires-Dist: requests>=2.31.0
21
- Requires-Dist: mkdocstrings[python]>=0.26.2,<0.31.0 ; extra == 'dev'
22
- Requires-Dist: mypy>=1.12.0,<2.0.0 ; extra == 'dev'
23
- Requires-Dist: pytest>=7.4.1,<9.0.0 ; extra == 'dev'
24
- Requires-Dist: python-dotenv>=1.0.0,<2.0.0 ; extra == 'dev'
25
- Requires-Dist: pytest-asyncio>=0.21.1,<1.2.0 ; extra == 'dev'
26
- Requires-Dist: pytest-codecov>=0.5.1,<0.8.0 ; extra == 'dev'
27
- Requires-Dist: ruff>=0.7,<0.13 ; extra == 'dev'
28
- Requires-Dist: mkdocs-material>=9.5.41,<10.0.0 ; extra == 'dev'
29
- Requires-Dist: mkdocstrings-python>=1.12.1,<2.0.0 ; extra == 'dev'
30
- Requires-Dist: types-pygments>=2.18.0.20240506 ; extra == 'dev'
31
- Requires-Dist: types-colorama>=0.4.15.20240311 ; extra == 'dev'
32
- Requires-Dist: types-requests>=2.32.0.20241016 ; extra == 'dev'
33
- Requires-Dist: types-setuptools>=75.2.0.20241018,<81.0.0.0 ; extra == 'dev'
34
21
  Requires-Python: >=3.12, <3.14
35
22
  Project-URL: Changelog, https://github.com/matthewcane/python-ntfy/releases
36
- Project-URL: Documentation, https://python-ntfy.readthedocs.io/
23
+ Project-URL: Documentation, https://matthewcane.github.io/python-ntfy/
37
24
  Project-URL: Homepage, https://github.com/matthewcane/python-ntfy
38
25
  Project-URL: Issues, https://github.com/matthewcane/python-ntfy/issues
39
26
  Project-URL: Repository, https://github.com/matthewcane/python-ntfy
40
- Provides-Extra: dev
41
27
  Description-Content-Type: text/markdown
42
28
 
43
29
  # A Python Library For ntfy
44
30
 
45
31
  ![GitHub Release](https://img.shields.io/github/v/release/MatthewCane/python-ntfy?display_name=release&label=latest%20release&link=https%3A%2F%2Fgithub.com%2FMatthewCane%2Fpython-ntfy%2Freleases%2Flatest)
46
- ![PyPI - Downloads](https://img.shields.io/pypi/dm/python-ntfy?logo=pypi&link=http%3A%2F%2Fpypi.org%2Fproject%2Fpython-ntfy%2F)
32
+ [![PyPI Downloads](https://static.pepy.tech/badge/python-ntfy/month)](https://pepy.tech/projects/python-ntfy)
47
33
  ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/MatthewCane/python-ntfy/publish.yml?logo=githubactions&link=https%3A%2F%2Fgithub.com%2FMatthewCane%2Fpython-ntfy%2Factions%2Fworkflows%2Fpublish.yml)
48
34
 
49
35
  An easy-to-use python library for the [ntfy notification service](https://ntfy.sh/). Aiming for full feature support and a super easy to use interface.
@@ -1,7 +1,7 @@
1
1
  # A Python Library For ntfy
2
2
 
3
3
  ![GitHub Release](https://img.shields.io/github/v/release/MatthewCane/python-ntfy?display_name=release&label=latest%20release&link=https%3A%2F%2Fgithub.com%2FMatthewCane%2Fpython-ntfy%2Freleases%2Flatest)
4
- ![PyPI - Downloads](https://img.shields.io/pypi/dm/python-ntfy?logo=pypi&link=http%3A%2F%2Fpypi.org%2Fproject%2Fpython-ntfy%2F)
4
+ [![PyPI Downloads](https://static.pepy.tech/badge/python-ntfy/month)](https://pepy.tech/projects/python-ntfy)
5
5
  ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/MatthewCane/python-ntfy/publish.yml?logo=githubactions&link=https%3A%2F%2Fgithub.com%2FMatthewCane%2Fpython-ntfy%2Factions%2Fworkflows%2Fpublish.yml)
6
6
 
7
7
  An easy-to-use python library for the [ntfy notification service](https://ntfy.sh/). Aiming for full feature support and a super easy to use interface.
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "python-ntfy"
3
- version = "0.8.1"
4
- description = "An ntfy library aiming for feature completeness"
3
+ version = "0.9.1"
4
+ description = "An easy-to-use library for the ntfy notification service."
5
5
  readme = "README.md"
6
6
  license = "MIT"
7
7
  requires-python = ">=3.12, <3.14"
@@ -24,7 +24,7 @@ authors = [{ name = "Matthew Cane", email = "matthew.cane0@gmail.com" }]
24
24
 
25
25
  [project.urls]
26
26
  Homepage = "https://github.com/matthewcane/python-ntfy"
27
- Documentation = "https://python-ntfy.readthedocs.io/"
27
+ Documentation = "https://matthewcane.github.io/python-ntfy/"
28
28
  Repository = "https://github.com/matthewcane/python-ntfy"
29
29
  Issues = "https://github.com/matthewcane/python-ntfy/issues"
30
30
  Changelog = "https://github.com/matthewcane/python-ntfy/releases"
@@ -37,24 +37,7 @@ build-backend = "uv_build"
37
37
  module-name = "python_ntfy"
38
38
  module-root = ""
39
39
 
40
- [tool.uv]
41
- dev-dependencies = [
42
- "mkdocstrings[python]>=0.26.2,<0.31.0",
43
- "mypy>=1.12.0,<2.0.0",
44
- "pytest>=7.4.1,<9.0.0",
45
- "python-dotenv>=1.0.0,<2.0.0",
46
- "pytest-asyncio>=0.21.1,<1.2.0",
47
- "pytest-codecov>=0.5.1,<0.8.0",
48
- "ruff>=0.7,<0.13",
49
- "mkdocs-material>=9.5.41,<10.0.0",
50
- "mkdocstrings-python>=1.12.1,<2.0.0",
51
- "types-pygments>=2.18.0.20240506",
52
- "types-colorama>=0.4.15.20240311",
53
- "types-requests>=2.32.0.20241016",
54
- "types-setuptools>=75.2.0.20241018,<81.0.0.0",
55
- ]
56
-
57
- [project.optional-dependencies]
40
+ [dependency-groups]
58
41
  dev = [
59
42
  "mkdocstrings[python]>=0.26.2,<0.31.0",
60
43
  "mypy>=1.12.0,<2.0.0",
@@ -74,6 +57,9 @@ dev = [
74
57
  [tool.ruff]
75
58
  target-version = "py312"
76
59
 
60
+ [tool.ruff.lint.isort]
61
+ combine-as-imports = true
62
+
77
63
  [tool.ruff.lint]
78
64
  select = [
79
65
  "E", # PycodeStyle errors
@@ -125,3 +111,20 @@ addopts = [
125
111
  "--cov-fail-under=95",
126
112
  "--cov-report=term-missing",
127
113
  ]
114
+
115
+ [tool.mypy]
116
+ python_version = "3.12"
117
+ warn_unused_ignores = true
118
+ warn_redundant_casts = true
119
+ warn_unreachable = true
120
+ no_implicit_optional = true
121
+ strict_equality = true
122
+ pretty = true
123
+ # Default expectations for the codebase; public modules may override to be stricter.
124
+ disallow_incomplete_defs = false
125
+ disallow_untyped_defs = false
126
+
127
+ [[tool.mypy.overrides]]
128
+ module = ["python_ntfy.client", "python_ntfy.__init__"]
129
+ disallow_incomplete_defs = true
130
+ disallow_untyped_defs = true
@@ -0,0 +1,17 @@
1
+ from ._exceptions import MessageSendError as MessageSendError
2
+ from ._send_functions import (
3
+ BroadcastAction as BroadcastAction,
4
+ HttpAction as HttpAction,
5
+ MessagePriority as MessagePriority,
6
+ ViewAction as ViewAction,
7
+ )
8
+ from .client import NtfyClient as NtfyClient
9
+
10
+ __all__ = [
11
+ "BroadcastAction",
12
+ "HttpAction",
13
+ "MessagePriority",
14
+ "MessageSendError",
15
+ "NtfyClient",
16
+ "ViewAction",
17
+ ]
@@ -0,0 +1,19 @@
1
+ """Compatibility shim for historical import path.
2
+
3
+ Prefer importing from `python_ntfy` package root:
4
+
5
+ from python_ntfy import NtfyClient
6
+
7
+ This module re-exports `NtfyClient` to maintain backward compatibility with
8
+ older references like `python_ntfy._ntfy.NtfyClient`.
9
+ """
10
+
11
+ from warnings import warn
12
+
13
+ from .client import NtfyClient as NtfyClient
14
+
15
+ warn(
16
+ "`python_ntfy._ntfy` is deprecated and will be removed in a future version. Please import from `python_ntfy` instead.",
17
+ DeprecationWarning,
18
+ stacklevel=2,
19
+ )
@@ -0,0 +1,146 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+
7
+ from ._get_functions import get_cached_messages as _get_cached_messages
8
+ from ._send_functions import (
9
+ BroadcastAction as _BroadcastAction,
10
+ HttpAction as _HttpAction,
11
+ MessagePriority as _MessagePriority,
12
+ ViewAction as _ViewAction,
13
+ send as _send_message,
14
+ send_file as _send_file,
15
+ )
16
+
17
+
18
+ class NtfyClient:
19
+ """A client for interacting with the ntfy notification service."""
20
+
21
+ # Backwards-compatible attribute exposure (discouraged for new code):
22
+ BroadcastAction = _BroadcastAction
23
+ HttpAction = _HttpAction
24
+ MessagePriority = _MessagePriority
25
+ ViewAction = _ViewAction
26
+
27
+ def __init__(
28
+ self,
29
+ topic: str,
30
+ server: str = "https://ntfy.sh",
31
+ auth: tuple[str, str] | str | None = None,
32
+ ) -> None:
33
+ """Initialize the client.
34
+
35
+ Args:
36
+ topic: The topic to use for this client.
37
+ server: The server base URL (must include protocol, e.g., https://).
38
+ auth: Credentials for this client. Takes precedence over environment
39
+ variables. May be a tuple ``(user, password)`` for Basic auth
40
+ or a token string for Bearer auth.
41
+ """
42
+ self._server = os.environ.get("NTFY_SERVER") or server
43
+ self._topic = topic
44
+ self.__set_url(self._server, topic)
45
+ self._auth: tuple[str, str] | None = self._resolve_auth(auth)
46
+
47
+ def _resolve_auth(
48
+ self, auth: tuple[str, str] | str | None
49
+ ) -> tuple[str, str] | None:
50
+ """Resolve authentication credentials using args or environment variables."""
51
+ # Explicitly provided credentials take precedence (including empty string)
52
+ if auth is not None:
53
+ if isinstance(auth, tuple):
54
+ return auth
55
+ if isinstance(auth, str):
56
+ return ("", auth)
57
+
58
+ # Fallback to environment variables
59
+ user = os.environ.get("NTFY_USER")
60
+ password = os.environ.get("NTFY_PASSWORD")
61
+ token = os.environ.get("NTFY_TOKEN")
62
+
63
+ if user and password:
64
+ return (user, password)
65
+ if token:
66
+ return ("", token)
67
+
68
+ return None
69
+
70
+ def __set_url(self, server: str, topic: str) -> None:
71
+ self.url = server.strip("/") + "/" + topic
72
+
73
+ def set_topic(self, topic: str) -> None:
74
+ """Set a new topic for this client."""
75
+ self._topic = topic
76
+ self.__set_url(self._server, self._topic)
77
+
78
+ def get_topic(self) -> str:
79
+ """Get the current topic."""
80
+ return self._topic
81
+
82
+ # Public API methods delegate to internal helpers for implementation
83
+
84
+ def send(
85
+ self,
86
+ message: str,
87
+ title: str | None = None,
88
+ priority: _MessagePriority = _MessagePriority.DEFAULT,
89
+ tags: list[str] | None = None,
90
+ actions: list[_ViewAction | _BroadcastAction | _HttpAction] | None = None,
91
+ schedule: datetime | None = None,
92
+ format_as_markdown: bool = False,
93
+ timeout_seconds: int = 5,
94
+ email: str | None = None,
95
+ ) -> dict:
96
+ """Send a text-based message to the server."""
97
+ return _send_message(
98
+ self,
99
+ message=message,
100
+ title=title,
101
+ priority=priority,
102
+ tags=tags,
103
+ actions=actions,
104
+ schedule=schedule,
105
+ format_as_markdown=format_as_markdown,
106
+ timeout_seconds=timeout_seconds,
107
+ email=email,
108
+ )
109
+
110
+ def send_file(
111
+ self,
112
+ file: str | Path,
113
+ title: str | None = None,
114
+ priority: _MessagePriority = _MessagePriority.DEFAULT,
115
+ tags: list[str] | None = None,
116
+ actions: list[_ViewAction | _BroadcastAction | _HttpAction] | None = None,
117
+ schedule: datetime | None = None,
118
+ timeout_seconds: int = 30,
119
+ email: str | None = None,
120
+ ) -> dict:
121
+ """Send a file to the server."""
122
+ return _send_file(
123
+ self,
124
+ file=file,
125
+ title=title,
126
+ priority=priority,
127
+ tags=tags,
128
+ actions=actions,
129
+ schedule=schedule,
130
+ timeout_seconds=timeout_seconds,
131
+ email=email,
132
+ )
133
+
134
+ def get_cached_messages(
135
+ self,
136
+ since: str = "all",
137
+ scheduled: bool = False,
138
+ timeout_seconds: int = 10,
139
+ ) -> list[dict]:
140
+ """Get cached messages from the server."""
141
+ return _get_cached_messages(
142
+ self,
143
+ since=since,
144
+ scheduled=scheduled,
145
+ timeout_seconds=timeout_seconds,
146
+ )
File without changes
@@ -1,3 +0,0 @@
1
- from ._ntfy import NtfyClient as NtfyClient
2
-
3
- __all__ = ["NtfyClient"]
@@ -1,134 +0,0 @@
1
- """This module provides the NtfyClient class for interacting with the ntfy notification service.
2
-
3
- The NtfyClient class allows users to send notifications, files, and perform various actions
4
- through the ntfy.sh service. It also supports retrieving cached messages.
5
-
6
- Typical usage example:
7
-
8
- client = NtfyClient(topic="my_topic")
9
- client.send("Hello, World!")
10
- """
11
-
12
- import os
13
-
14
- from ._get_functions import get_cached_messages
15
- from ._send_functions import (
16
- BroadcastAction,
17
- HttpAction,
18
- MessagePriority,
19
- ViewAction,
20
- send,
21
- send_file,
22
- )
23
-
24
-
25
- class GetFunctionsMixin:
26
- """Mixin for getting messages."""
27
-
28
- get_cached_messages = get_cached_messages
29
-
30
-
31
- class SendFunctionsMixin:
32
- """Mixin for sending messages."""
33
-
34
- send = send
35
- send_file = send_file
36
- BroadcastAction = BroadcastAction
37
- HttpAction = HttpAction
38
- MessagePriority = MessagePriority
39
- ViewAction = ViewAction
40
-
41
-
42
- class NtfyClient(GetFunctionsMixin, SendFunctionsMixin):
43
- """A class for interacting with the ntfy notification service."""
44
-
45
- def __init__(
46
- self,
47
- topic: str,
48
- server: str = "https://ntfy.sh",
49
- auth: tuple[str, str] | str | None = None,
50
- ) -> None:
51
- """Itinialize the NtfyClient.
52
-
53
- Args:
54
- topic: The topic to use for this client
55
- server: The server to connect to. Must include the protocol (http/https)
56
- auth: The authentication credentials to use for this client. Takes precedence over environment variables. Can be a tuple of (user, password) or a token.
57
-
58
- Returns:
59
- None
60
-
61
- Exceptions:
62
- None
63
-
64
- Examples:
65
- client = NtfyClient(topic="my_topic")
66
- """
67
- self._server = os.environ.get("NTFY_SERVER") or server
68
- self._topic = topic
69
- self.__set_url(self._server, topic)
70
- self._auth: tuple[str, str] | None = self._resolve_auth(auth)
71
-
72
- def _resolve_auth(
73
- self, auth: tuple[str, str] | str | None
74
- ) -> tuple[str, str] | None:
75
- """Resolve the authentication credentials.
76
-
77
- Args:
78
- auth: The authentication credentials to use for this client. Takes precedence over environment variables. Can be a tuple of (user, password) or a token string.
79
-
80
- Returns:
81
- tuple[str, str] | None: The authentication credentials.
82
- """
83
- # If the user has supplied credentials, use them (including empty string)
84
- if auth is not None:
85
- if isinstance(auth, tuple):
86
- return auth
87
- if isinstance(auth, str):
88
- return ("", auth)
89
-
90
- # Otherwise, check environment variables
91
- user = os.environ.get("NTFY_USER")
92
- password = os.environ.get("NTFY_PASSWORD")
93
- token = os.environ.get("NTFY_TOKEN")
94
-
95
- if user and password:
96
- return (user, password)
97
-
98
- if token:
99
- return ("", token)
100
-
101
- # If no credentials are found, return None
102
- return None
103
-
104
- def __set_url(
105
- self,
106
- server,
107
- topic,
108
- ) -> None:
109
- self.url = server.strip("/") + "/" + topic
110
-
111
- def set_topic(
112
- self,
113
- topic: str,
114
- ) -> None:
115
- """Set a new topic for the client.
116
-
117
- Args:
118
- topic: The topic to set for this client.
119
-
120
- Returns:
121
- None
122
- """
123
- self._topic = topic
124
- self.__set_url(self._server, self._topic)
125
-
126
- def get_topic(
127
- self,
128
- ) -> str:
129
- """Get the current topic.
130
-
131
- Returns:
132
- str: The current topic.
133
- """
134
- return self._topic