pylemetry 0.1.3__tar.gz → 0.1.4__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.
Files changed (29) hide show
  1. {pylemetry-0.1.3 → pylemetry-0.1.4}/.github/workflows/release.yaml +4 -1
  2. {pylemetry-0.1.3 → pylemetry-0.1.4}/PKG-INFO +35 -5
  3. {pylemetry-0.1.3 → pylemetry-0.1.4}/README.md +34 -4
  4. {pylemetry-0.1.3 → pylemetry-0.1.4}/pyproject.toml +1 -1
  5. pylemetry-0.1.4/src/pylemetry/decorators/count.py +35 -0
  6. pylemetry-0.1.4/src/pylemetry/decorators/time.py +34 -0
  7. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/meters/timer.py +19 -1
  8. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/test_pylemetry/decorators/test_count.py +11 -1
  9. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/test_pylemetry/decorators/test_time.py +11 -1
  10. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/test_pylemetry/meters/test_timer.py +16 -0
  11. {pylemetry-0.1.3 → pylemetry-0.1.4}/uv.lock +1 -1
  12. pylemetry-0.1.3/src/pylemetry/decorators/count.py +0 -32
  13. pylemetry-0.1.3/src/pylemetry/decorators/time.py +0 -31
  14. {pylemetry-0.1.3 → pylemetry-0.1.4}/.github/actions/configure-uv/action.yaml +0 -0
  15. {pylemetry-0.1.3 → pylemetry-0.1.4}/.github/workflows/ci.yaml +0 -0
  16. {pylemetry-0.1.3 → pylemetry-0.1.4}/.gitignore +0 -0
  17. {pylemetry-0.1.3 → pylemetry-0.1.4}/LICENSE +0 -0
  18. {pylemetry-0.1.3 → pylemetry-0.1.4}/py.typed +0 -0
  19. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/__init__.py +0 -0
  20. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/__init__.py +0 -0
  21. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/decorators/__init__.py +0 -0
  22. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/meters/__init__.py +0 -0
  23. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/meters/counter.py +0 -0
  24. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/meters/gauge.py +0 -0
  25. {pylemetry-0.1.3 → pylemetry-0.1.4}/src/pylemetry/registry.py +0 -0
  26. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/conftest.py +0 -0
  27. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/test_pylemetry/meters/test_counter.py +0 -0
  28. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/test_pylemetry/meters/test_gauge.py +0 -0
  29. {pylemetry-0.1.3 → pylemetry-0.1.4}/test/test_pylemetry/test_registry.py +0 -0
@@ -42,6 +42,8 @@ jobs:
42
42
 
43
43
  steps:
44
44
  - uses: actions/checkout@v5
45
+ with:
46
+ ssh-key: ${{ secrets.DEPLOY_KEY }}
45
47
 
46
48
  - uses: ./.github/actions/configure-uv
47
49
 
@@ -72,4 +74,5 @@ jobs:
72
74
  - name: Commit Version Bump
73
75
  uses: EndBug/add-and-commit@v9
74
76
  with:
75
- message: "Bump project version following release"
77
+ message: "Bump project version following release [skip ci]"
78
+ default_author: github_actions
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylemetry
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: A Python metrics library
5
5
  Project-URL: Homepage, https://pypi.org/project/pylemetry/
6
6
  Project-URL: Repository, https://github.com/amurphy4/pylemetry
@@ -22,6 +22,13 @@ Description-Content-Type: text/markdown
22
22
 
23
23
  # Pylemetry
24
24
 
25
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
26
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
27
+ [![image](https://img.shields.io/pypi/v/pylemetry.svg)](https://pypi.python.org/pypi/pylemetry)
28
+ [![image](https://img.shields.io/pypi/l/pylemetry.svg)](https://pypi.python.org/pypi/pylemetry)
29
+ [![image](https://img.shields.io/pypi/pyversions/pylemetry.svg)](https://pypi.python.org/pypi/pylemetry)
30
+ [![Release](https://github.com/amurphy4/pylemetry/actions/workflows/release.yaml/badge.svg?branch=main)](https://github.com/amurphy4/pylemetry/actions/workflows/release.yaml)
31
+
25
32
  Add metrics to your Python applications with Pylemetry
26
33
 
27
34
  Currently, three meters are supported, `Counter`, `Gauge`, and `Timer`
@@ -51,20 +58,29 @@ from pylemetry import Registry
51
58
  from pylemetry.decorators import count
52
59
 
53
60
 
54
- @count
61
+ @count()
55
62
  def some_method() -> None:
56
63
  ...
57
64
 
58
65
 
66
+ @count("named_counter")
67
+ def another_method() -> None:
68
+ ...
69
+
70
+
59
71
  def main() -> None:
60
72
  for _ in range(100):
61
73
  some_method()
74
+ another_method()
62
75
 
63
76
  counter = Registry().get_counter("some_method")
64
77
  counter.get_count() # 100
78
+
79
+ counter = Registry.get_counter("named_counter")
80
+ counter.get_count() # 100
65
81
  ```
66
82
 
67
- When using this meter via a decorator, the meter gets added to the global `Registry`, with the method name it's decorating as the meter name
83
+ When using this meter via a decorator, the meter gets added to the global `Registry`, with the method name it's decorating as the meter name. Alternatively, you can provide a name for the meter as a parameter to the decorator
68
84
 
69
85
  ## Gauge
70
86
 
@@ -95,7 +111,7 @@ gauge.get_value() # 11.5
95
111
 
96
112
  gauge.subtract(10)
97
113
  gauge -= 8.5
98
- gauge.get_value() # -7.5
114
+ gauge.get_value() # -8
99
115
 
100
116
  gauge.set_value(7.5)
101
117
  gauge.get_value() # 7.5
@@ -127,20 +143,34 @@ from pylemetry import Registry
127
143
  from pylemetry.decorators import time
128
144
 
129
145
 
130
- @time
146
+ @time()
131
147
  def some_method() -> None:
132
148
  ...
133
149
 
134
150
 
151
+ @time("named_timer")
152
+ def another_method() -> None:
153
+ ...
154
+
155
+
135
156
  def main() -> None:
136
157
  for _ in range(100):
137
158
  some_method()
159
+ another_method()
138
160
 
139
161
  timer = Registry().get_timer("some_method")
140
162
  timer.get_count() # 100
141
163
  timer.get_mean_tick_time() # Mean execution time of the some_method function
164
+ timer.get_max_tick_time() # Maximum execution time of the some_method function
165
+ timer.get_min_tick_time() # Minimum execution time of the some_method function
166
+
167
+ timer = Registry().get_timer("named_timer")
168
+ timer.get_count() # 100
169
+ ...
142
170
  ```
143
171
 
172
+ When using this meter via a decorator, the meter gets added to the global `Registry`, with the method name it's decorating as the meter name. Alternatively, you can provide a name for the meter as a parameter to the decorator
173
+
144
174
  ## The Registry
145
175
 
146
176
  Pylemetry maintains a global registry of meters, allowing you to share a meter across multiple files, or reference metrics from a central location.
@@ -1,5 +1,12 @@
1
1
  # Pylemetry
2
2
 
3
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
4
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5
+ [![image](https://img.shields.io/pypi/v/pylemetry.svg)](https://pypi.python.org/pypi/pylemetry)
6
+ [![image](https://img.shields.io/pypi/l/pylemetry.svg)](https://pypi.python.org/pypi/pylemetry)
7
+ [![image](https://img.shields.io/pypi/pyversions/pylemetry.svg)](https://pypi.python.org/pypi/pylemetry)
8
+ [![Release](https://github.com/amurphy4/pylemetry/actions/workflows/release.yaml/badge.svg?branch=main)](https://github.com/amurphy4/pylemetry/actions/workflows/release.yaml)
9
+
3
10
  Add metrics to your Python applications with Pylemetry
4
11
 
5
12
  Currently, three meters are supported, `Counter`, `Gauge`, and `Timer`
@@ -29,20 +36,29 @@ from pylemetry import Registry
29
36
  from pylemetry.decorators import count
30
37
 
31
38
 
32
- @count
39
+ @count()
33
40
  def some_method() -> None:
34
41
  ...
35
42
 
36
43
 
44
+ @count("named_counter")
45
+ def another_method() -> None:
46
+ ...
47
+
48
+
37
49
  def main() -> None:
38
50
  for _ in range(100):
39
51
  some_method()
52
+ another_method()
40
53
 
41
54
  counter = Registry().get_counter("some_method")
42
55
  counter.get_count() # 100
56
+
57
+ counter = Registry.get_counter("named_counter")
58
+ counter.get_count() # 100
43
59
  ```
44
60
 
45
- When using this meter via a decorator, the meter gets added to the global `Registry`, with the method name it's decorating as the meter name
61
+ When using this meter via a decorator, the meter gets added to the global `Registry`, with the method name it's decorating as the meter name. Alternatively, you can provide a name for the meter as a parameter to the decorator
46
62
 
47
63
  ## Gauge
48
64
 
@@ -73,7 +89,7 @@ gauge.get_value() # 11.5
73
89
 
74
90
  gauge.subtract(10)
75
91
  gauge -= 8.5
76
- gauge.get_value() # -7.5
92
+ gauge.get_value() # -8
77
93
 
78
94
  gauge.set_value(7.5)
79
95
  gauge.get_value() # 7.5
@@ -105,20 +121,34 @@ from pylemetry import Registry
105
121
  from pylemetry.decorators import time
106
122
 
107
123
 
108
- @time
124
+ @time()
109
125
  def some_method() -> None:
110
126
  ...
111
127
 
112
128
 
129
+ @time("named_timer")
130
+ def another_method() -> None:
131
+ ...
132
+
133
+
113
134
  def main() -> None:
114
135
  for _ in range(100):
115
136
  some_method()
137
+ another_method()
116
138
 
117
139
  timer = Registry().get_timer("some_method")
118
140
  timer.get_count() # 100
119
141
  timer.get_mean_tick_time() # Mean execution time of the some_method function
142
+ timer.get_max_tick_time() # Maximum execution time of the some_method function
143
+ timer.get_min_tick_time() # Minimum execution time of the some_method function
144
+
145
+ timer = Registry().get_timer("named_timer")
146
+ timer.get_count() # 100
147
+ ...
120
148
  ```
121
149
 
150
+ When using this meter via a decorator, the meter gets added to the global `Registry`, with the method name it's decorating as the meter name. Alternatively, you can provide a name for the meter as a parameter to the decorator
151
+
122
152
  ## The Registry
123
153
 
124
154
  Pylemetry maintains a global registry of meters, allowing you to share a meter across multiple files, or reference metrics from a central location.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pylemetry"
3
- version = "0.1.3"
3
+ version = "0.1.4"
4
4
  description = "A Python metrics library"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -0,0 +1,35 @@
1
+ from typing import Callable, Any, Optional
2
+
3
+ from functools import wraps
4
+
5
+ from pylemetry import Registry
6
+ from pylemetry.meters import Counter
7
+
8
+
9
+ def count(name: Optional[str] = None) -> Callable[..., Any]:
10
+ """
11
+ Decorator to count the number of invocations of a given callable. Creates a Counter meter in the Registry
12
+ with either the provided name or the fully qualified name of the callable object as the metric name.
13
+
14
+ :param name: Name of the meter to create, if None the function name is used
15
+ :return: Result of the wrapped function
16
+ """
17
+
18
+ def decorator(f: Callable[..., Any]) -> Callable[..., Any]:
19
+ @wraps(f)
20
+ def wrapper() -> Any:
21
+ counter_name = f.__qualname__ if name is None else name
22
+
23
+ counter = Registry().get_counter(counter_name)
24
+
25
+ if not counter:
26
+ counter = Counter()
27
+ Registry().add_counter(counter_name, counter)
28
+
29
+ counter += 1
30
+
31
+ return f()
32
+
33
+ return wrapper
34
+
35
+ return decorator
@@ -0,0 +1,34 @@
1
+ from typing import Callable, Any, Optional
2
+
3
+ from functools import wraps
4
+
5
+ from pylemetry import Registry
6
+ from pylemetry.meters import Timer
7
+
8
+
9
+ def time(name: Optional[str] = None) -> Callable[..., Any]:
10
+ """
11
+ Decorator to time the invocations of a given callable. Creates a Timer meter in the Registry with either the
12
+ provided name or the fully qualified name of the callable object as the metric name.
13
+
14
+ :param name: Name of the meter to create, if None the function name is used
15
+ :return: Result of the wrapped function
16
+ """
17
+
18
+ def decorator(f: Callable[..., Any]) -> Callable[..., Any]:
19
+ @wraps(f)
20
+ def wrapper() -> Any:
21
+ time_name = f.__qualname__ if name is None else name
22
+
23
+ _timer = Registry().get_timer(time_name)
24
+
25
+ if not _timer:
26
+ _timer = Timer()
27
+ Registry().add_timer(time_name, _timer)
28
+
29
+ with _timer.time():
30
+ return f()
31
+
32
+ return wrapper
33
+
34
+ return decorator
@@ -24,7 +24,7 @@ class Timer:
24
24
  @contextmanager
25
25
  def time(self) -> Generator[None, None, None]:
26
26
  """
27
- Context manager to time a code block and add the result to the internal ticks list
27
+ Context manager to time in seconds a code block and add the result to the internal ticks list
28
28
  """
29
29
 
30
30
  start_time = time.perf_counter()
@@ -53,3 +53,21 @@ class Timer:
53
53
  """
54
54
 
55
55
  return sum(self.ticks) / len(self.ticks)
56
+
57
+ def get_max_tick_time(self) -> float:
58
+ """
59
+ Get the maximum tick time from the list of ticks within this timer
60
+
61
+ :return: Maximum tick time
62
+ """
63
+
64
+ return max(self.ticks)
65
+
66
+ def get_min_tick_time(self) -> float:
67
+ """
68
+ Get the minimum tick time from the list of ticks within this timer
69
+
70
+ :return: Minimum tick time
71
+ """
72
+
73
+ return min(self.ticks)
@@ -5,7 +5,7 @@ from pylemetry.decorators import count
5
5
  from pylemetry.meters import Counter
6
6
 
7
7
 
8
- @count
8
+ @count()
9
9
  def mock_function() -> str:
10
10
  return "A function decorated with the count decorator"
11
11
 
@@ -36,3 +36,13 @@ def test_count_decorator_updates_existing_counter(call_count: int) -> None:
36
36
 
37
37
  assert isinstance(counter, Counter)
38
38
  assert counter.get_count() == call_count
39
+
40
+
41
+ def test_count_decorator_with_name() -> None:
42
+ @count(name="test_count_meter")
43
+ def mock() -> None:
44
+ print("Mock method")
45
+
46
+ mock()
47
+
48
+ assert "test_count_meter" in Registry().counters
@@ -5,7 +5,7 @@ from pylemetry.decorators import time
5
5
  from pylemetry.meters import Timer
6
6
 
7
7
 
8
- @time
8
+ @time()
9
9
  def mock_function() -> str:
10
10
  return "A function decorated with the timer decorator"
11
11
 
@@ -38,3 +38,13 @@ def test_count_decorator_updates_existing_counter(call_count: int) -> None:
38
38
  assert isinstance(timer, Timer)
39
39
  assert timer.get_count() == call_count
40
40
  assert 0 < timer.get_mean_tick_time() < 0.05
41
+
42
+
43
+ def test_time_decorator_with_name() -> None:
44
+ @time(name="test_timer_meter")
45
+ def mock() -> None:
46
+ print("Mock method")
47
+
48
+ mock()
49
+
50
+ assert "test_timer_meter" in Registry().timers
@@ -36,3 +36,19 @@ def test_get_mean_tick_time() -> None:
36
36
  timer.ticks = [1, 2, 3, 4, 5]
37
37
 
38
38
  assert timer.get_mean_tick_time() == 3
39
+
40
+
41
+ def test_get_max_tick_time() -> None:
42
+ timer = Timer()
43
+
44
+ timer.ticks = [1, 2, 3, 4, 5]
45
+
46
+ assert timer.get_max_tick_time() == 5
47
+
48
+
49
+ def test_get_min_tick_time() -> None:
50
+ timer = Timer()
51
+
52
+ timer.ticks = [1, 2, 3, 4, 5]
53
+
54
+ assert timer.get_min_tick_time() == 1
@@ -246,7 +246,7 @@ wheels = [
246
246
 
247
247
  [[package]]
248
248
  name = "pylemetry"
249
- version = "0.1.3"
249
+ version = "0.1.4"
250
250
  source = { editable = "." }
251
251
 
252
252
  [package.dev-dependencies]
@@ -1,32 +0,0 @@
1
- from typing import Callable, Any
2
-
3
- from functools import wraps
4
-
5
- from pylemetry import Registry
6
- from pylemetry.meters import Counter
7
-
8
-
9
- def count(f: Callable[..., Any]) -> Callable[..., Any]:
10
- """
11
- Decorator to count the number of invocations of a given callable. Creates a Counter meter in the Registry
12
- with the fully qualified name of the callable object as the metric name.
13
-
14
- :param f: Callable to wrap
15
- :return: Result of f
16
- """
17
-
18
- @wraps(f)
19
- def wrapper() -> Any:
20
- counter_name = f.__qualname__
21
-
22
- counter = Registry().get_counter(counter_name)
23
-
24
- if not counter:
25
- counter = Counter()
26
- Registry().add_counter(counter_name, counter)
27
-
28
- counter += 1
29
-
30
- return f()
31
-
32
- return wrapper
@@ -1,31 +0,0 @@
1
- from typing import Callable, Any
2
-
3
- from functools import wraps
4
-
5
- from pylemetry import Registry
6
- from pylemetry.meters import Timer
7
-
8
-
9
- def time(f: Callable[..., Any]) -> Callable[..., Any]:
10
- """
11
- Decorator to time the invocations of a given callable. Creates a Timer meter in the Registry with the fully
12
- qualified name of the callable object as the metric name.
13
-
14
- :param f: Callable to wrap
15
- :return: Result of f
16
- """
17
-
18
- @wraps(f)
19
- def wrapper() -> Any:
20
- time_name = f.__qualname__
21
-
22
- _timer = Registry().get_timer(time_name)
23
-
24
- if not _timer:
25
- _timer = Timer()
26
- Registry().add_timer(time_name, _timer)
27
-
28
- with _timer.time():
29
- return f()
30
-
31
- return wrapper
File without changes
File without changes
File without changes
File without changes
File without changes