nano-dev-utils 0.5.8__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,38 +7,57 @@ 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
15
  def timeit(
16
- self, iterations: int = 1
16
+ self,
17
+ iterations: int = 1,
18
+ timeout: float | None = None,
19
+ per_iteration: bool = False,
17
20
  ) -> Callable[[Callable[P, R]], Callable[P, R | None]]:
18
- def decorator(func: Callable[P, R]) -> Callable[P, R | None]:
19
- """Decorator that times function execution with automatic unit scaling and averaging."""
21
+ """Decorator that times function execution with optional timeout support."""
20
22
 
23
+ def decorator(func: Callable[P, R]) -> Callable[P, R | None]:
21
24
  @wraps(func)
22
25
  def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | None:
23
- total_elapsed = 0
24
- result = None
26
+ total_elapsed_ns = 0
27
+ result: R | None = None
25
28
 
26
- for _ in range(iterations):
27
- start = time.perf_counter_ns()
29
+ for i in range(1, iterations + 1):
30
+ start_ns = time.perf_counter_ns()
28
31
  result = func(*args, **kwargs)
29
- total_elapsed += time.perf_counter_ns() - start
32
+ duration_ns = time.perf_counter_ns() - start_ns
33
+ total_elapsed_ns += duration_ns
30
34
 
31
- avg_elapsed = total_elapsed / iterations
32
- value = avg_elapsed
33
- unit = 'ns'
34
-
35
- for divisor, unit in self.units:
36
- if avg_elapsed >= divisor or unit == 'ns':
37
- value = avg_elapsed / divisor
38
- 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
+ )
39
52
 
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
+ )
40
59
  extra_info = f'{args} {kwargs} ' if self.verbose else ''
41
- iter_info = f' (avg over {iterations} runs)' if iterations > 1 else ''
60
+ iter_info = f' (avg. over {iterations} runs)' if iterations > 1 else ''
42
61
  print(
43
62
  f'{func.__name__} {extra_info}took {value:.{self.precision}f} [{unit}]{iter_info}'
44
63
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nano_dev_utils
3
- Version: 0.5.8
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,23 +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`.
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`.
36
34
 
37
35
  * **`timeit(
38
- self, iterations: int = 1
36
+ self,
37
+ iterations: int = 1,
38
+ timeout: float | None = None,
39
+ per_iteration: bool = False
39
40
  ) -> Callable[[Callable[P, R]], Callable[P, R | None]]`**:
40
- Decorator that times function execution with automatic unit scaling.
41
- * When the decorated function is called, this decorator records the start and end times,
42
- calculates the average execution time, prints the function name and execution
43
- time (optionally including arguments), and returns the result of the original function.
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)
44
54
 
45
55
  #### Example Usage:
46
56
 
@@ -50,16 +60,22 @@ from nano_dev_utils.timers import Timer
50
60
 
51
61
  timer = Timer(precision=6, verbose=True)
52
62
 
53
-
63
+ # Basic timing
54
64
  @timer.timeit()
55
65
  def my_function(a, b=10):
56
- """A sample function."""
57
- time.sleep(0.1)
58
- return a + b
59
-
60
-
61
- result = my_function(5, b=20)
62
- 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
63
79
  ```
64
80
 
65
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=IiCltOHRkYqfX_IzHQ2Xty4ptITBiaOldFO1HhQ6r_A,1748
5
- nano_dev_utils-0.5.8.dist-info/METADATA,sha256=KA_vxHbiStc8At1rFrWu2Rt8G_eJzyrRLeb3tYQWfUs,5550
6
- nano_dev_utils-0.5.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- nano_dev_utils-0.5.8.dist-info/licenses/LICENSE,sha256=Muenl7Bw_LdtHZtlOMAP7Kt97gDCq8WWp2605eDWhHU,1089
8
- nano_dev_utils-0.5.8.dist-info/RECORD,,