nano-dev-utils 0.5.7__py3-none-any.whl → 1.0.0__py3-none-any.whl

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.

Potentially problematic release.


This version of nano-dev-utils might be problematic. Click here for more details.

nano_dev_utils/timers.py CHANGED
@@ -7,32 +7,62 @@ R = TypeVar('R')
7
7
 
8
8
 
9
9
  class Timer:
10
- def __init__(self, precision=4, verbose=False):
10
+ def __init__(self, precision: int = 4, verbose: bool = False):
11
11
  self.precision = precision
12
12
  self.verbose = verbose
13
13
  self.units = [(1e9, 's'), (1e6, 'ms'), (1e3, 'μs'), (1.0, 'ns')]
14
14
 
15
- def timeit(self, func: Callable[P, R]) -> Callable[P, R]:
16
- """Decorator that times function execution with automatic unit scaling."""
15
+ def timeit(
16
+ self,
17
+ iterations: int = 1,
18
+ timeout: float | None = None,
19
+ per_iteration: bool = False,
20
+ ) -> Callable[[Callable[P, R]], Callable[P, R | None]]:
21
+ """Decorator that times function execution with optional timeout support."""
17
22
 
18
- @wraps(func)
19
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
20
- start = time.perf_counter_ns()
21
- result = func(*args, **kwargs)
22
- elapsed = time.perf_counter_ns() - start
23
+ def decorator(func: Callable[P, R]) -> Callable[P, R | None]:
24
+ @wraps(func)
25
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | None:
26
+ total_elapsed_ns = 0
27
+ result: R | None = None
23
28
 
24
- value = elapsed
25
- unit = 'ns'
29
+ for i in range(1, iterations + 1):
30
+ start_ns = time.perf_counter_ns()
31
+ result = func(*args, **kwargs)
32
+ duration_ns = time.perf_counter_ns() - start_ns
33
+ total_elapsed_ns += duration_ns
26
34
 
27
- for divisor, unit in self.units:
28
- if elapsed >= divisor or unit == 'ns':
29
- value = elapsed / divisor
30
- break
35
+ if timeout is not None:
36
+ if per_iteration:
37
+ duration_s = duration_ns / 1e9
38
+ if duration_s > timeout:
39
+ raise TimeoutError(
40
+ f'{func.__name__} exceeded '
41
+ f'{timeout:.{self.precision}f}s on '
42
+ f'iteration {i} (took '
43
+ f'{duration_s:.{self.precision}f}s)'
44
+ )
45
+ else:
46
+ total_duration_s = total_elapsed_ns / 1e9
47
+ if total_duration_s > timeout:
48
+ raise TimeoutError(
49
+ f'{func.__name__} exceeded {timeout:.{self.precision}f}s '
50
+ f'after {i} iterations (took {total_duration_s:.{self.precision}f}s)'
51
+ )
31
52
 
32
- extra_info = f'{args} {kwargs} ' if self.verbose else ''
33
- print(
34
- f'{func.__name__} {extra_info}took {value:.{self.precision}f} [{unit}]'
35
- )
36
- return result
53
+ avg_elapsed_ns = total_elapsed_ns / iterations
54
+ value, unit = next(
55
+ (avg_elapsed_ns / div, u)
56
+ for div, u in self.units
57
+ if avg_elapsed_ns >= div or u == 'ns'
58
+ )
59
+ extra_info = f'{args} {kwargs} ' if self.verbose else ''
60
+ iter_info = f' (avg. over {iterations} runs)' if iterations > 1 else ''
61
+ print(
62
+ f'{func.__name__} {extra_info}took {value:.{self.precision}f} [{unit}]{iter_info}'
63
+ )
64
+ return result
37
65
 
38
- return wrapper
66
+ return wrapper
67
+
68
+ return decorator
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nano_dev_utils
3
- Version: 0.5.7
3
+ Version: 1.0.0
4
4
  Summary: A collection of small Python utilities for developers.
5
5
  Project-URL: Homepage, https://github.com/yaronday/nano_utils
6
6
  Project-URL: Issues, https://github.com/yaronday/nano_utils/issues
@@ -24,21 +24,33 @@ A collection of small Python utilities for developers.
24
24
 
25
25
  ### `timers.py`
26
26
 
27
- This module provides a `Timer` class for measuring the execution time of code blocks and functions.
27
+ This module provides a `Timer` class for measuring the execution time of code blocks and functions with additional features like timeout control and multi-iteration averaging.
28
28
 
29
29
  #### `Timer` Class
30
30
 
31
31
  * **`__init__(self, precision: int = 4, verbose: bool = False)`**: Initializes a `Timer` instance.
32
- * `precision`: The number of decimal places to record and
33
- display time durations. Defaults to 4.
34
- * `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs).
35
- Defaults to `False`.
36
-
37
- * **`timeit(self, func: Callable[P, R]) -> Callable[P, R]`**:
38
- Decorator that times function execution with automatic unit scaling.
39
- * When the decorated function is called, this decorator records the start and end times,
40
- calculates the total execution time, prints the function name and execution
41
- time (optionally including arguments), and returns the result of the original function.
32
+ * `precision`: The number of decimal places to record and display time durations. Defaults to 4.
33
+ * `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs). Defaults to `False`.
34
+
35
+ * **`timeit(
36
+ self,
37
+ iterations: int = 1,
38
+ timeout: float | None = None,
39
+ per_iteration: bool = False
40
+ ) -> Callable[[Callable[P, R]], Callable[P, R | None]]`**:
41
+ Decorator that times function execution with advanced features:
42
+ * `iterations`: Number of times to run the function (for averaging). Defaults to 1.
43
+ * `timeout`: Maximum allowed execution time in seconds. When exceeded:
44
+ * Raises `TimeoutError` immediately
45
+ * **Warning:** The function execution will be aborted mid-operation
46
+ * No return value will be available if timeout occurs
47
+ * `per_iteration`: If True, applies timeout check to each iteration; otherwise checks total time across all iterations.
48
+ * Features:
49
+ * Records execution times
50
+ * Handles timeout conditions
51
+ * Calculates average execution time across iterations
52
+ * Prints the function name and execution time (with optional arguments)
53
+ * Returns the result of the original function (unless timeout occurs)
42
54
 
43
55
  #### Example Usage:
44
56
 
@@ -48,16 +60,22 @@ from nano_dev_utils.timers import Timer
48
60
 
49
61
  timer = Timer(precision=6, verbose=True)
50
62
 
51
-
52
- @timer.timeit
63
+ # Basic timing
64
+ @timer.timeit()
53
65
  def my_function(a, b=10):
54
- """A sample function."""
55
- time.sleep(0.1)
56
- return a + b
57
-
58
-
59
- result = my_function(5, b=20)
60
- print(f"Result: {result}")
66
+ """A sample function."""
67
+ time.sleep(0.1)
68
+ return a + b
69
+
70
+ # Advanced usage with timeout and iterations
71
+ @timer.timeit(iterations=5, timeout=0.5, per_iteration=True)
72
+ def critical_function(x):
73
+ """Function with timeout check per iteration."""
74
+ time.sleep(0.08)
75
+ return x * 2
76
+
77
+ result1 = my_function(5, b=20) # Shows args/kwargs and timing
78
+ result2 = critical_function(10) # Runs 5 times with per-iteration timeout
61
79
  ```
62
80
 
63
81
  ### `dynamic_importer.py`
@@ -0,0 +1,8 @@
1
+ nano_dev_utils/__init__.py,sha256=imiI367TPj5s4IFmi-VrKJLbdkIxdIPISNscthoaS9U,454
2
+ nano_dev_utils/dynamic_importer.py,sha256=cm2VwDYSGwhGZNO3uMX-O0LaKtEFtzkPm7BrZW4igG4,911
3
+ nano_dev_utils/release_ports.py,sha256=sgmoPax9Hpcse1rHbBSnDJWTkvV6aWpZ5hQFxBKhGR8,5886
4
+ nano_dev_utils/timers.py,sha256=dTbmf2O10YQw_Gz_fVATdZXqxgSpTjTlbeekd_jpLyw,2875
5
+ nano_dev_utils-1.0.0.dist-info/METADATA,sha256=YOD8JC-1a-gaDHF5-VYu3Qtr5-uqHlsSorPguSZvk58,6498
6
+ nano_dev_utils-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ nano_dev_utils-1.0.0.dist-info/licenses/LICENSE,sha256=Muenl7Bw_LdtHZtlOMAP7Kt97gDCq8WWp2605eDWhHU,1089
8
+ nano_dev_utils-1.0.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- nano_dev_utils/__init__.py,sha256=imiI367TPj5s4IFmi-VrKJLbdkIxdIPISNscthoaS9U,454
2
- nano_dev_utils/dynamic_importer.py,sha256=cm2VwDYSGwhGZNO3uMX-O0LaKtEFtzkPm7BrZW4igG4,911
3
- nano_dev_utils/release_ports.py,sha256=sgmoPax9Hpcse1rHbBSnDJWTkvV6aWpZ5hQFxBKhGR8,5886
4
- nano_dev_utils/timers.py,sha256=EJFFU9y5qv9w9mfjtBsrgyCXj7NoBpXH0AzPewFnRa0,1205
5
- nano_dev_utils-0.5.7.dist-info/METADATA,sha256=NsqOX4UXr2EhEW7qUkLz_5qL95B9PmqTuDLR4NsNkVY,5498
6
- nano_dev_utils-0.5.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- nano_dev_utils-0.5.7.dist-info/licenses/LICENSE,sha256=Muenl7Bw_LdtHZtlOMAP7Kt97gDCq8WWp2605eDWhHU,1089
8
- nano_dev_utils-0.5.7.dist-info/RECORD,,