pythonkuma 0.4.0rc0__tar.gz → 0.5.0__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonkuma
3
- Version: 0.4.0rc0
3
+ Version: 0.5.0
4
4
  Summary: Simple Python wrapper for Uptime Kuma
5
5
  Project-URL: Source, https://github.com/tr4nt0r/pythonkuma
6
6
  Project-URL: Documentation, https://tr4nt0r.github.io/pythonkuma
@@ -20,10 +20,9 @@ Description-Content-Type: text/markdown
20
20
  Simple Python wrapper for Uptime Kuma
21
21
 
22
22
  [![build](https://github.com/tr4nt0r/pythonkuma/workflows/Build/badge.svg)](https://github.com/tr4nt0r/pythonkuma/actions)
23
- [![codecov](https://codecov.io/gh/tr4nt0r/pythonkuma/graph/badge.svg?token=RM3MC4LP07)](https://codecov.io/gh/pythonkuma/pynecil)
23
+ [![codecov](https://codecov.io/gh/tr4nt0r/pythonkuma/graph/badge.svg?token=YmUNsziQH0)](https://codecov.io/gh/tr4nt0r/pythonkuma)
24
24
  [![PyPI version](https://badge.fury.io/py/pythonkuma.svg)](https://badge.fury.io/py/pythonkuma)
25
25
  ![PyPI - Downloads](https://img.shields.io/pypi/dm/pythonkuma?style=flat&label=pypi%20downloads)
26
- [!["Buy Me A Coffee"](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://www.buymeacoffee.com/tr4nt0r)
27
26
  [![GitHub Sponsor](https://img.shields.io/badge/GitHub-Sponsor-blue?logo=github)](https://github.com/sponsors/tr4nt0r)
28
27
 
29
28
  ---
@@ -3,10 +3,9 @@
3
3
  Simple Python wrapper for Uptime Kuma
4
4
 
5
5
  [![build](https://github.com/tr4nt0r/pythonkuma/workflows/Build/badge.svg)](https://github.com/tr4nt0r/pythonkuma/actions)
6
- [![codecov](https://codecov.io/gh/tr4nt0r/pythonkuma/graph/badge.svg?token=RM3MC4LP07)](https://codecov.io/gh/pythonkuma/pynecil)
6
+ [![codecov](https://codecov.io/gh/tr4nt0r/pythonkuma/graph/badge.svg?token=YmUNsziQH0)](https://codecov.io/gh/tr4nt0r/pythonkuma)
7
7
  [![PyPI version](https://badge.fury.io/py/pythonkuma.svg)](https://badge.fury.io/py/pythonkuma)
8
8
  ![PyPI - Downloads](https://img.shields.io/pypi/dm/pythonkuma?style=flat&label=pypi%20downloads)
9
- [!["Buy Me A Coffee"](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://www.buymeacoffee.com/tr4nt0r)
10
9
  [![GitHub Sponsor](https://img.shields.io/badge/GitHub-Sponsor-blue?logo=github)](https://github.com/sponsors/tr4nt0r)
11
10
 
12
11
  ---
@@ -37,19 +37,26 @@ include = [
37
37
  "/pythonkuma",
38
38
  ]
39
39
 
40
+ [[tool.hatch.envs.hatch-test.matrix]]
41
+ python = ["3.14", "3.13", "3.12"]
42
+
40
43
  [tool.hatch.envs.default]
41
44
  dependencies = [
42
- "ruff==0.15.0",
45
+ "ruff==0.15.1",
43
46
  "aiohttp==3.13.3",
44
47
  "prometheus-client==0.24.1",
45
48
  "mashumaro==3.20",
46
- "mkdocs-material==9.7.1",
49
+ "mkdocs-material==9.7.2",
47
50
  "mkdocstrings[python]==1.0.3",
51
+ "pytest-asyncio==1.3.0",
52
+ "pytest==9.0.2",
53
+ "pytest-cov==7.0.0",
54
+ "syrupy==5.1.0",
48
55
  ]
49
56
 
50
57
  [tool.hatch.envs.hatch-static-analysis]
51
58
  dependencies = [
52
- "ruff==0.15.0",
59
+ "ruff==0.15.1",
53
60
  ]
54
61
  config-path = "none"
55
62
 
@@ -63,7 +70,10 @@ pythonpath = ["pythonkuma"]
63
70
  [tool.hatch.envs.hatch-test]
64
71
  extra-dependencies = [
65
72
  "pytest-cov==7.0.0",
73
+ "pytest-asyncio==1.3.0",
74
+ "syrupy==5.1.0",
66
75
  ]
76
+ extra-args = ["--cov-report=xml", "-vv"]
67
77
 
68
78
  [tool.hatch.envs.default.scripts]
69
79
  docs-serve = "mkdocs serve"
@@ -83,6 +93,9 @@ indent-style = "space"
83
93
  select = ["ALL"]
84
94
  ignore = ["TRY003", "COM812", "N818", "C901"]
85
95
 
96
+ [tool.ruff.lint.per-file-ignores]
97
+ "tests/*" = ["S101", "TC002", "TC003"]
98
+
86
99
  [lint.per-file-ignores]
87
100
  "**/scripts/*" = [
88
101
  "INP001",
@@ -5,12 +5,13 @@ from .exceptions import (
5
5
  UptimeKumaAuthenticationException,
6
6
  UptimeKumaConnectionException,
7
7
  UptimeKumaException,
8
+ UptimeKumaParseException,
8
9
  )
9
10
  from .models import MonitorStatus, MonitorType, UptimeKumaMonitor, UptimeKumaVersion
10
11
  from .update import UpdateChecker
11
12
  from .uptimekuma import UptimeKuma
12
13
 
13
- __version__ = "0.4.0rc0"
14
+ __version__ = "0.5.0"
14
15
 
15
16
  __all__ = [
16
17
  "MonitorStatus",
@@ -22,5 +23,6 @@ __all__ = [
22
23
  "UptimeKumaConnectionException",
23
24
  "UptimeKumaException",
24
25
  "UptimeKumaMonitor",
26
+ "UptimeKumaParseException",
25
27
  "UptimeKumaVersion",
26
28
  ]
@@ -13,5 +13,9 @@ class UptimeKumaAuthenticationException(UptimeKumaException):
13
13
  """Uptime Kuma authentication exception."""
14
14
 
15
15
 
16
+ class UptimeKumaParseException(UptimeKumaException):
17
+ """Exception raised when parsing of Prometheus metrics fails."""
18
+
19
+
16
20
  class UpdateException(Exception):
17
21
  """Exception raised for errors fetching latest release from github."""
@@ -92,6 +92,8 @@ class UptimeKumaMonitor(UptimeKumaBaseModel):
92
92
  monitor_response_time_seconds_30d: float | None = None
93
93
  monitor_response_time_seconds_365d: float | None = None
94
94
 
95
+ monitor_tags: list[str]
96
+
95
97
 
96
98
  @dataclass
97
99
  class UptimeKumaVersion(UptimeKumaBaseModel):
@@ -13,9 +13,23 @@ from aiohttp import (
13
13
  from prometheus_client.parser import text_string_to_metric_families
14
14
  from yarl import URL
15
15
 
16
- from .exceptions import UptimeKumaAuthenticationException, UptimeKumaConnectionException
16
+ from .exceptions import (
17
+ UptimeKumaAuthenticationException,
18
+ UptimeKumaConnectionException,
19
+ UptimeKumaParseException,
20
+ )
17
21
  from .models import UptimeKumaMonitor, UptimeKumaVersion
18
22
 
23
+ COMMON_LABELS = (
24
+ "monitor_id",
25
+ "monitor_name",
26
+ "monitor_type",
27
+ "monitor_url",
28
+ "monitor_hostname",
29
+ "monitor_port",
30
+ "window",
31
+ )
32
+
19
33
 
20
34
  class UptimeKuma:
21
35
  """Uptime Kuma client."""
@@ -89,28 +103,39 @@ class UptimeKuma:
89
103
  raise UptimeKumaConnectionException(msg, str(url)) from e
90
104
  except ClientError as e:
91
105
  raise UptimeKumaConnectionException from e
92
- else:
93
- for metric in text_string_to_metric_families(await request.text()):
94
- if metric.name == "app_version" and metric.samples:
95
- self.version = UptimeKumaVersion.from_dict(metric.samples[0].labels)
96
- if not metric.name.startswith("monitor"):
97
- continue
98
- for sample in metric.samples:
99
- key = (
100
- int(monitor_id)
101
- if (monitor_id := sample.labels.get("monitor_id"))
102
- else sample.labels["monitor_name"]
103
- )
104
-
105
- name = (
106
- f"{sample.name}_{window}"
107
- if (window := sample.labels.get("window"))
108
- else sample.name
109
- )
110
-
111
- monitors.setdefault(key, sample.labels).update({name: sample.value})
112
-
113
- return {
114
- key: UptimeKumaMonitor.from_dict(value)
115
- for key, value in monitors.items()
116
- }
106
+
107
+ try:
108
+ metrics = list(text_string_to_metric_families(await request.text()))
109
+ except ValueError as e:
110
+ raise UptimeKumaParseException from e
111
+
112
+ for metric in metrics:
113
+ if metric.name == "app_version" and metric.samples:
114
+ self.version = UptimeKumaVersion.from_dict(metric.samples[0].labels)
115
+ if not metric.name.startswith("monitor"):
116
+ continue
117
+ for sample in metric.samples:
118
+ key = (
119
+ int(monitor_id)
120
+ if (monitor_id := sample.labels.get("monitor_id"))
121
+ else sample.labels["monitor_name"]
122
+ )
123
+
124
+ tags = [
125
+ f"{k}:{v}" if v else k
126
+ for k, v in sample.labels.items()
127
+ if k not in COMMON_LABELS
128
+ ]
129
+ name = (
130
+ f"{sample.name}_{window}"
131
+ if (window := sample.labels.get("window"))
132
+ else sample.name
133
+ )
134
+
135
+ monitors.setdefault(
136
+ key, {**sample.labels, "monitor_tags": tags}
137
+ ).update({name: sample.value})
138
+
139
+ return {
140
+ key: UptimeKumaMonitor.from_dict(value) for key, value in monitors.items()
141
+ }
File without changes
File without changes