nano-dev-utils 0.5.7__tar.gz → 0.5.8__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.
Potentially problematic release.
This version of nano-dev-utils might be problematic. Click here for more details.
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/nano_dev_utils.iml +3 -1
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/workspace.xml +97 -5
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/PKG-INFO +6 -4
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/README.md +5 -3
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/pyproject.toml +1 -1
- nano_dev_utils-0.5.8/src/nano_dev_utils/timers.py +49 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/tests/test_timer.py +30 -8
- nano_dev_utils-0.5.7/src/nano_dev_utils/timers.py +0 -38
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.gitignore +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/.gitignore +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/misc.xml +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/modules.xml +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/vcs.xml +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/LICENSE +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/src/nano_dev_utils/__init__.py +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/src/nano_dev_utils/dynamic_importer.py +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/src/nano_dev_utils/release_ports.py +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/tests/__init__.py +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/tests/test_dynamic_importer.py +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/tests/test_release_ports.py +0 -0
- {nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/uv.lock +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<module type="PYTHON_MODULE" version="4">
|
|
3
3
|
<component name="NewModuleRootManager">
|
|
4
|
-
<content url="file://$MODULE_DIR$"
|
|
4
|
+
<content url="file://$MODULE_DIR$">
|
|
5
|
+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
6
|
+
</content>
|
|
5
7
|
<orderEntry type="jdk" jdkName="Python 3.10 (nano_dev_utils)" jdkType="Python SDK" />
|
|
6
8
|
<orderEntry type="sourceFolder" forTests="false" />
|
|
7
9
|
</component>
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
<option name="autoReloadType" value="SELECTIVE" />
|
|
5
5
|
</component>
|
|
6
6
|
<component name="ChangeListManager">
|
|
7
|
-
<list default="true" id="1859e23b-7665-4b92-98cc-65e07a208923" name="Changes" comment="
|
|
7
|
+
<list default="true" id="1859e23b-7665-4b92-98cc-65e07a208923" name="Changes" comment="corrected return types - complete">
|
|
8
|
+
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
|
8
9
|
<change beforePath="$PROJECT_DIR$/pyproject.toml" beforeDir="false" afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
|
|
10
|
+
<change beforePath="$PROJECT_DIR$/src/nano_dev_utils/timers.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/nano_dev_utils/timers.py" afterDir="false" />
|
|
11
|
+
<change beforePath="$PROJECT_DIR$/tests/test_timer.py" beforeDir="false" afterPath="$PROJECT_DIR$/tests/test_timer.py" afterDir="false" />
|
|
9
12
|
</list>
|
|
10
13
|
<option name="SHOW_DIALOG" value="false" />
|
|
11
14
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
@@ -15,7 +18,7 @@
|
|
|
15
18
|
<component name="Git.Settings">
|
|
16
19
|
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
|
17
20
|
<map>
|
|
18
|
-
<entry key="$PROJECT_DIR$" value="
|
|
21
|
+
<entry key="$PROJECT_DIR$" value="FI" />
|
|
19
22
|
</map>
|
|
20
23
|
</option>
|
|
21
24
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
|
@@ -32,7 +35,9 @@
|
|
|
32
35
|
</component>
|
|
33
36
|
<component name="PropertiesComponent"><![CDATA[{
|
|
34
37
|
"keyToString": {
|
|
38
|
+
"Python tests.Python tests in test_timer.py.executor": "Run",
|
|
35
39
|
"Python tests.Python tests in tests.executor": "Run",
|
|
40
|
+
"Python.test_timer.executor": "Run",
|
|
36
41
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
|
37
42
|
"git-widget-placeholder": "master",
|
|
38
43
|
"ignore.virus.scanning.warn.message": "true",
|
|
@@ -45,7 +50,44 @@
|
|
|
45
50
|
<recent name="C:\GitHubWS\nano_dev_utils" />
|
|
46
51
|
</key>
|
|
47
52
|
</component>
|
|
48
|
-
<component name="RunManager">
|
|
53
|
+
<component name="RunManager" selected="Python tests.Python tests in tests">
|
|
54
|
+
<configuration name="test_timer" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
|
55
|
+
<module name="nano_dev_utils" />
|
|
56
|
+
<option name="ENV_FILES" value="" />
|
|
57
|
+
<option name="INTERPRETER_OPTIONS" value="" />
|
|
58
|
+
<option name="PARENT_ENVS" value="true" />
|
|
59
|
+
<envs>
|
|
60
|
+
<env name="PYTHONUNBUFFERED" value="1" />
|
|
61
|
+
</envs>
|
|
62
|
+
<option name="SDK_HOME" value="" />
|
|
63
|
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/tests" />
|
|
64
|
+
<option name="IS_MODULE_SDK" value="true" />
|
|
65
|
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
|
66
|
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
|
67
|
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/tests/test_timer.py" />
|
|
68
|
+
<option name="PARAMETERS" value="" />
|
|
69
|
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
|
70
|
+
<option name="EMULATE_TERMINAL" value="false" />
|
|
71
|
+
<option name="MODULE_MODE" value="false" />
|
|
72
|
+
<option name="REDIRECT_INPUT" value="false" />
|
|
73
|
+
<option name="INPUT_FILE" value="" />
|
|
74
|
+
<method v="2" />
|
|
75
|
+
</configuration>
|
|
76
|
+
<configuration name="Python tests in test_timer.py" type="tests" factoryName="Autodetect" temporary="true" nameIsGenerated="true">
|
|
77
|
+
<module name="nano_dev_utils" />
|
|
78
|
+
<option name="ENV_FILES" value="" />
|
|
79
|
+
<option name="INTERPRETER_OPTIONS" value="" />
|
|
80
|
+
<option name="PARENT_ENVS" value="true" />
|
|
81
|
+
<option name="SDK_HOME" value="" />
|
|
82
|
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/tests" />
|
|
83
|
+
<option name="IS_MODULE_SDK" value="true" />
|
|
84
|
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
|
85
|
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
|
86
|
+
<option name="_new_additionalArguments" value="""" />
|
|
87
|
+
<option name="_new_target" value=""$PROJECT_DIR$/tests/test_timer.py"" />
|
|
88
|
+
<option name="_new_targetType" value=""PATH"" />
|
|
89
|
+
<method v="2" />
|
|
90
|
+
</configuration>
|
|
49
91
|
<configuration name="Python tests in tests" type="tests" factoryName="Autodetect" temporary="true" nameIsGenerated="true">
|
|
50
92
|
<module name="nano_dev_utils" />
|
|
51
93
|
<option name="ENV_FILES" value="" />
|
|
@@ -64,6 +106,9 @@
|
|
|
64
106
|
<recent_temporary>
|
|
65
107
|
<list>
|
|
66
108
|
<item itemvalue="Python tests.Python tests in tests" />
|
|
109
|
+
<item itemvalue="Python tests.Python tests in tests" />
|
|
110
|
+
<item itemvalue="Python tests.Python tests in test_timer.py" />
|
|
111
|
+
<item itemvalue="Python.test_timer" />
|
|
67
112
|
</list>
|
|
68
113
|
</recent_temporary>
|
|
69
114
|
</component>
|
|
@@ -139,9 +184,52 @@
|
|
|
139
184
|
<option name="project" value="LOCAL" />
|
|
140
185
|
<updated>1747321637844</updated>
|
|
141
186
|
</task>
|
|
142
|
-
<
|
|
187
|
+
<task id="LOCAL-00008" summary="+iterations parameter">
|
|
188
|
+
<option name="closed" value="true" />
|
|
189
|
+
<created>1747660086270</created>
|
|
190
|
+
<option name="number" value="00008" />
|
|
191
|
+
<option name="presentableId" value="LOCAL-00008" />
|
|
192
|
+
<option name="project" value="LOCAL" />
|
|
193
|
+
<updated>1747660086270</updated>
|
|
194
|
+
</task>
|
|
195
|
+
<task id="LOCAL-00009" summary="minor update">
|
|
196
|
+
<option name="closed" value="true" />
|
|
197
|
+
<created>1747661192289</created>
|
|
198
|
+
<option name="number" value="00009" />
|
|
199
|
+
<option name="presentableId" value="LOCAL-00009" />
|
|
200
|
+
<option name="project" value="LOCAL" />
|
|
201
|
+
<updated>1747661192289</updated>
|
|
202
|
+
</task>
|
|
203
|
+
<task id="LOCAL-00010" summary="corrected return type">
|
|
204
|
+
<option name="closed" value="true" />
|
|
205
|
+
<created>1747665494128</created>
|
|
206
|
+
<option name="number" value="00010" />
|
|
207
|
+
<option name="presentableId" value="LOCAL-00010" />
|
|
208
|
+
<option name="project" value="LOCAL" />
|
|
209
|
+
<updated>1747665494128</updated>
|
|
210
|
+
</task>
|
|
211
|
+
<task id="LOCAL-00011" summary="corrected return types - complete">
|
|
212
|
+
<option name="closed" value="true" />
|
|
213
|
+
<created>1747666293914</created>
|
|
214
|
+
<option name="number" value="00011" />
|
|
215
|
+
<option name="presentableId" value="LOCAL-00011" />
|
|
216
|
+
<option name="project" value="LOCAL" />
|
|
217
|
+
<updated>1747666293914</updated>
|
|
218
|
+
</task>
|
|
219
|
+
<option name="localTasksCounter" value="12" />
|
|
143
220
|
<servers />
|
|
144
221
|
</component>
|
|
222
|
+
<component name="Vcs.Log.Tabs.Properties">
|
|
223
|
+
<option name="TAB_STATES">
|
|
224
|
+
<map>
|
|
225
|
+
<entry key="MAIN">
|
|
226
|
+
<value>
|
|
227
|
+
<State />
|
|
228
|
+
</value>
|
|
229
|
+
</entry>
|
|
230
|
+
</map>
|
|
231
|
+
</option>
|
|
232
|
+
</component>
|
|
145
233
|
<component name="VcsManagerConfiguration">
|
|
146
234
|
<MESSAGE value="." />
|
|
147
235
|
<MESSAGE value="license relative path" />
|
|
@@ -150,6 +238,10 @@
|
|
|
150
238
|
<MESSAGE value="adding license url" />
|
|
151
239
|
<MESSAGE value="+pre-commit config" />
|
|
152
240
|
<MESSAGE value="removed [tool.hatch.build]" />
|
|
153
|
-
<
|
|
241
|
+
<MESSAGE value="+iterations parameter" />
|
|
242
|
+
<MESSAGE value="minor update" />
|
|
243
|
+
<MESSAGE value="corrected return type" />
|
|
244
|
+
<MESSAGE value="corrected return types - complete" />
|
|
245
|
+
<option name="LAST_COMMIT_MESSAGE" value="corrected return types - complete" />
|
|
154
246
|
</component>
|
|
155
247
|
</project>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nano_dev_utils
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.8
|
|
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
|
|
@@ -34,10 +34,12 @@ This module provides a `Timer` class for measuring the execution time of code bl
|
|
|
34
34
|
* `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs).
|
|
35
35
|
Defaults to `False`.
|
|
36
36
|
|
|
37
|
-
* **`timeit(
|
|
37
|
+
* **`timeit(
|
|
38
|
+
self, iterations: int = 1
|
|
39
|
+
) -> Callable[[Callable[P, R]], Callable[P, R | None]]`**:
|
|
38
40
|
Decorator that times function execution with automatic unit scaling.
|
|
39
41
|
* When the decorated function is called, this decorator records the start and end times,
|
|
40
|
-
calculates the
|
|
42
|
+
calculates the average execution time, prints the function name and execution
|
|
41
43
|
time (optionally including arguments), and returns the result of the original function.
|
|
42
44
|
|
|
43
45
|
#### Example Usage:
|
|
@@ -49,7 +51,7 @@ from nano_dev_utils.timers import Timer
|
|
|
49
51
|
timer = Timer(precision=6, verbose=True)
|
|
50
52
|
|
|
51
53
|
|
|
52
|
-
@timer.timeit
|
|
54
|
+
@timer.timeit()
|
|
53
55
|
def my_function(a, b=10):
|
|
54
56
|
"""A sample function."""
|
|
55
57
|
time.sleep(0.1)
|
|
@@ -16,10 +16,12 @@ This module provides a `Timer` class for measuring the execution time of code bl
|
|
|
16
16
|
* `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs).
|
|
17
17
|
Defaults to `False`.
|
|
18
18
|
|
|
19
|
-
* **`timeit(
|
|
19
|
+
* **`timeit(
|
|
20
|
+
self, iterations: int = 1
|
|
21
|
+
) -> Callable[[Callable[P, R]], Callable[P, R | None]]`**:
|
|
20
22
|
Decorator that times function execution with automatic unit scaling.
|
|
21
23
|
* When the decorated function is called, this decorator records the start and end times,
|
|
22
|
-
calculates the
|
|
24
|
+
calculates the average execution time, prints the function name and execution
|
|
23
25
|
time (optionally including arguments), and returns the result of the original function.
|
|
24
26
|
|
|
25
27
|
#### Example Usage:
|
|
@@ -31,7 +33,7 @@ from nano_dev_utils.timers import Timer
|
|
|
31
33
|
timer = Timer(precision=6, verbose=True)
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
@timer.timeit
|
|
36
|
+
@timer.timeit()
|
|
35
37
|
def my_function(a, b=10):
|
|
36
38
|
"""A sample function."""
|
|
37
39
|
time.sleep(0.1)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
import time
|
|
3
|
+
from typing import Callable, ParamSpec, TypeVar
|
|
4
|
+
|
|
5
|
+
P = ParamSpec('P')
|
|
6
|
+
R = TypeVar('R')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Timer:
|
|
10
|
+
def __init__(self, precision=4, verbose=False):
|
|
11
|
+
self.precision = precision
|
|
12
|
+
self.verbose = verbose
|
|
13
|
+
self.units = [(1e9, 's'), (1e6, 'ms'), (1e3, 'μs'), (1.0, 'ns')]
|
|
14
|
+
|
|
15
|
+
def timeit(
|
|
16
|
+
self, iterations: int = 1
|
|
17
|
+
) -> 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."""
|
|
20
|
+
|
|
21
|
+
@wraps(func)
|
|
22
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | None:
|
|
23
|
+
total_elapsed = 0
|
|
24
|
+
result = None
|
|
25
|
+
|
|
26
|
+
for _ in range(iterations):
|
|
27
|
+
start = time.perf_counter_ns()
|
|
28
|
+
result = func(*args, **kwargs)
|
|
29
|
+
total_elapsed += time.perf_counter_ns() - start
|
|
30
|
+
|
|
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
|
|
39
|
+
|
|
40
|
+
extra_info = f'{args} {kwargs} ' if self.verbose else ''
|
|
41
|
+
iter_info = f' (avg over {iterations} runs)' if iterations > 1 else ''
|
|
42
|
+
print(
|
|
43
|
+
f'{func.__name__} {extra_info}took {value:.{self.precision}f} [{unit}]{iter_info}'
|
|
44
|
+
)
|
|
45
|
+
return result
|
|
46
|
+
|
|
47
|
+
return wrapper
|
|
48
|
+
|
|
49
|
+
return decorator
|
|
@@ -18,7 +18,7 @@ def test_timeit_simple(mocker):
|
|
|
18
18
|
mock_time = mocker.patch('time.perf_counter_ns', side_effect=[0, 9.23467e5])
|
|
19
19
|
timer = Timer(precision=2)
|
|
20
20
|
|
|
21
|
-
@timer.timeit
|
|
21
|
+
@timer.timeit()
|
|
22
22
|
def sample_function():
|
|
23
23
|
return 'result'
|
|
24
24
|
|
|
@@ -33,7 +33,7 @@ def test_timeit_no_args_kwargs(mocker):
|
|
|
33
33
|
mock_time = mocker.patch('time.perf_counter_ns', side_effect=[1.0, 1.5])
|
|
34
34
|
timer = Timer(precision=2, verbose=True)
|
|
35
35
|
|
|
36
|
-
@timer.timeit
|
|
36
|
+
@timer.timeit()
|
|
37
37
|
def yet_another_function():
|
|
38
38
|
return 'yet another result'
|
|
39
39
|
|
|
@@ -49,7 +49,7 @@ def test_multithreaded_timing(mocker):
|
|
|
49
49
|
timer = Timer()
|
|
50
50
|
results = []
|
|
51
51
|
|
|
52
|
-
@timer.timeit
|
|
52
|
+
@timer.timeit()
|
|
53
53
|
def threaded_operation():
|
|
54
54
|
time.sleep(0.1)
|
|
55
55
|
return threading.get_ident()
|
|
@@ -77,7 +77,7 @@ def test_verbose_mode(mocker):
|
|
|
77
77
|
mocker.patch('time.perf_counter_ns', side_effect=[1e4, 5.23456e4])
|
|
78
78
|
verbose_timer = Timer(verbose=True)
|
|
79
79
|
|
|
80
|
-
@verbose_timer.timeit
|
|
80
|
+
@verbose_timer.timeit()
|
|
81
81
|
def func_with_args(a, b, c=3):
|
|
82
82
|
return a + b + c
|
|
83
83
|
|
|
@@ -96,9 +96,9 @@ def test_nested_timers(mocker):
|
|
|
96
96
|
mock_print = mocker.patch('builtins.print')
|
|
97
97
|
timer = Timer()
|
|
98
98
|
|
|
99
|
-
@timer.timeit
|
|
99
|
+
@timer.timeit()
|
|
100
100
|
def outer():
|
|
101
|
-
@timer.timeit
|
|
101
|
+
@timer.timeit()
|
|
102
102
|
def inner():
|
|
103
103
|
time.sleep(0.1)
|
|
104
104
|
|
|
@@ -134,7 +134,7 @@ def test_unit_scaling(mocker):
|
|
|
134
134
|
mocker.patch('time.perf_counter_ns', side_effect=[0, ns])
|
|
135
135
|
timer = Timer(precision=2)
|
|
136
136
|
|
|
137
|
-
@timer.timeit
|
|
137
|
+
@timer.timeit()
|
|
138
138
|
def dummy():
|
|
139
139
|
pass
|
|
140
140
|
|
|
@@ -150,10 +150,32 @@ def test_function_metadata_preserved():
|
|
|
150
150
|
"""Test that function metadata (name, docstring) is preserved"""
|
|
151
151
|
timer = Timer(precision=3)
|
|
152
152
|
|
|
153
|
-
@timer.timeit
|
|
153
|
+
@timer.timeit()
|
|
154
154
|
def dummy_func():
|
|
155
155
|
"""Test docstring"""
|
|
156
156
|
pass
|
|
157
157
|
|
|
158
158
|
assert dummy_func.__name__ == 'dummy_func'
|
|
159
159
|
assert dummy_func.__doc__ == 'Test docstring'
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_timeit_with_iterations(mocker):
|
|
163
|
+
mock_print = mocker.patch('builtins.print')
|
|
164
|
+
mock_time = mocker.patch(
|
|
165
|
+
'time.perf_counter_ns', side_effect=[0, 1000, 0, 2000, 0, 3000]
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
timer = Timer(precision=2)
|
|
169
|
+
|
|
170
|
+
@timer.timeit(iterations=3)
|
|
171
|
+
def sample_function():
|
|
172
|
+
return 'done'
|
|
173
|
+
|
|
174
|
+
result = sample_function()
|
|
175
|
+
|
|
176
|
+
assert result == 'done'
|
|
177
|
+
mock_time.assert_any_call()
|
|
178
|
+
|
|
179
|
+
mock_print.assert_called_once_with(
|
|
180
|
+
'sample_function took 2.00 [μs] (avg over 3 runs)'
|
|
181
|
+
)
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from functools import wraps
|
|
2
|
-
import time
|
|
3
|
-
from typing import Callable, ParamSpec, TypeVar
|
|
4
|
-
|
|
5
|
-
P = ParamSpec('P')
|
|
6
|
-
R = TypeVar('R')
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Timer:
|
|
10
|
-
def __init__(self, precision=4, verbose=False):
|
|
11
|
-
self.precision = precision
|
|
12
|
-
self.verbose = verbose
|
|
13
|
-
self.units = [(1e9, 's'), (1e6, 'ms'), (1e3, 'μs'), (1.0, 'ns')]
|
|
14
|
-
|
|
15
|
-
def timeit(self, func: Callable[P, R]) -> Callable[P, R]:
|
|
16
|
-
"""Decorator that times function execution with automatic unit scaling."""
|
|
17
|
-
|
|
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
|
-
|
|
24
|
-
value = elapsed
|
|
25
|
-
unit = 'ns'
|
|
26
|
-
|
|
27
|
-
for divisor, unit in self.units:
|
|
28
|
-
if elapsed >= divisor or unit == 'ns':
|
|
29
|
-
value = elapsed / divisor
|
|
30
|
-
break
|
|
31
|
-
|
|
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
|
|
37
|
-
|
|
38
|
-
return wrapper
|
|
File without changes
|
|
File without changes
|
{nano_dev_utils-0.5.7 → nano_dev_utils-0.5.8}/.idea/inspectionProfiles/profiles_settings.xml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|