nano-dev-utils 0.3.4__tar.gz → 0.4.1__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.
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/workspace.xml +45 -15
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/PKG-INFO +35 -26
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/README.md +35 -26
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/pyproject.toml +1 -1
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/src/nano_dev_utils/release_ports.py +2 -7
- nano_dev_utils-0.4.1/src/nano_dev_utils/timers.py +39 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/tests/testing_release_ports.py +4 -3
- nano_dev_utils-0.3.4/src/nano_dev_utils/timers.py +0 -35
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.gitignore +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/.gitignore +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/misc.xml +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/modules.xml +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/nano_dev_utils.iml +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.idea/vcs.xml +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/LICENSE.md +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/src/nano_dev_utils/__init__.py +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/src/nano_dev_utils/dynamic_importer.py +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/tests/__init__.py +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/tests/testing_dynamic_importer.py +0 -0
- {nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/tests/testing_timer.py +0 -0
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
<option name="autoReloadType" value="SELECTIVE" />
|
|
5
5
|
</component>
|
|
6
6
|
<component name="ChangeListManager">
|
|
7
|
-
<list default="true" id="96bbbefe-efb6-42c4-93da-e069ac3e654f" name="Changes" comment="
|
|
7
|
+
<list default="true" id="96bbbefe-efb6-42c4-93da-e069ac3e654f" name="Changes" comment="release_ports: Externalizing logger's config to a user's app. timers: improve code, docstring and type hinting README updates IAW with the above changes Version update: 0.4.0">
|
|
8
|
+
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
|
9
|
+
<change beforePath="$PROJECT_DIR$/pyproject.toml" beforeDir="false" afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
|
|
10
|
+
<change beforePath="$PROJECT_DIR$/tests/testing_release_ports.py" beforeDir="false" afterPath="$PROJECT_DIR$/tests/testing_release_ports.py" afterDir="false" />
|
|
11
|
+
</list>
|
|
8
12
|
<option name="SHOW_DIALOG" value="false" />
|
|
9
13
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
10
14
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
@@ -27,18 +31,18 @@
|
|
|
27
31
|
<option name="showLibraryContents" value="true" />
|
|
28
32
|
<option name="showMembers" value="true" />
|
|
29
33
|
</component>
|
|
30
|
-
<component name="PropertiesComponent"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
<component name="PropertiesComponent">{
|
|
35
|
+
"keyToString": {
|
|
36
|
+
"Python tests.Python tests in testing_release_ports.py.executor": "Run",
|
|
37
|
+
"Python tests.Python tests in testing_timer.py.executor": "Run",
|
|
38
|
+
"Python tests.Python tests in tests.executor": "Run",
|
|
39
|
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
|
40
|
+
"git-widget-placeholder": "master",
|
|
41
|
+
"ignore.virus.scanning.warn.message": "true",
|
|
42
|
+
"last_opened_file_path": "C:/GitHubWS/nano_dev_utils",
|
|
43
|
+
"settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable"
|
|
40
44
|
}
|
|
41
|
-
}
|
|
45
|
+
}</component>
|
|
42
46
|
<component name="RunManager" selected="Python tests.Python tests in tests">
|
|
43
47
|
<configuration name="Python tests in testing_release_ports.py" type="tests" factoryName="Autodetect" temporary="true" nameIsGenerated="true">
|
|
44
48
|
<module name="nano_dev_utils" />
|
|
@@ -88,8 +92,8 @@
|
|
|
88
92
|
<recent_temporary>
|
|
89
93
|
<list>
|
|
90
94
|
<item itemvalue="Python tests.Python tests in tests" />
|
|
91
|
-
<item itemvalue="Python tests.Python tests in testing_timer.py" />
|
|
92
95
|
<item itemvalue="Python tests.Python tests in testing_release_ports.py" />
|
|
96
|
+
<item itemvalue="Python tests.Python tests in testing_timer.py" />
|
|
93
97
|
<item itemvalue="Python tests.Python tests in testing_release_ports.py" />
|
|
94
98
|
</list>
|
|
95
99
|
</recent_temporary>
|
|
@@ -238,7 +242,31 @@
|
|
|
238
242
|
<option name="project" value="LOCAL" />
|
|
239
243
|
<updated>1745715934159</updated>
|
|
240
244
|
</task>
|
|
241
|
-
<
|
|
245
|
+
<task id="LOCAL-00017" summary="readme typo fixes">
|
|
246
|
+
<option name="closed" value="true" />
|
|
247
|
+
<created>1745716694896</created>
|
|
248
|
+
<option name="number" value="00017" />
|
|
249
|
+
<option name="presentableId" value="LOCAL-00017" />
|
|
250
|
+
<option name="project" value="LOCAL" />
|
|
251
|
+
<updated>1745716694896</updated>
|
|
252
|
+
</task>
|
|
253
|
+
<task id="LOCAL-00018" summary="minor update">
|
|
254
|
+
<option name="closed" value="true" />
|
|
255
|
+
<created>1745716727869</created>
|
|
256
|
+
<option name="number" value="00018" />
|
|
257
|
+
<option name="presentableId" value="LOCAL-00018" />
|
|
258
|
+
<option name="project" value="LOCAL" />
|
|
259
|
+
<updated>1745716727869</updated>
|
|
260
|
+
</task>
|
|
261
|
+
<task id="LOCAL-00019" summary="release_ports: Externalizing logger's config to a user's app. timers: improve code, docstring and type hinting README updates IAW with the above changes Version update: 0.4.0">
|
|
262
|
+
<option name="closed" value="true" />
|
|
263
|
+
<created>1745763645981</created>
|
|
264
|
+
<option name="number" value="00019" />
|
|
265
|
+
<option name="presentableId" value="LOCAL-00019" />
|
|
266
|
+
<option name="project" value="LOCAL" />
|
|
267
|
+
<updated>1745763645981</updated>
|
|
268
|
+
</task>
|
|
269
|
+
<option name="localTasksCounter" value="20" />
|
|
242
270
|
<servers />
|
|
243
271
|
</component>
|
|
244
272
|
<component name="Vcs.Log.Tabs.Properties">
|
|
@@ -265,7 +293,9 @@
|
|
|
265
293
|
<MESSAGE value="dunder init update" />
|
|
266
294
|
<MESSAGE value="fixed authors and url for pip show" />
|
|
267
295
|
<MESSAGE value="version update" />
|
|
296
|
+
<MESSAGE value="readme typo fixes" />
|
|
268
297
|
<MESSAGE value="minor update" />
|
|
269
|
-
<
|
|
298
|
+
<MESSAGE value="release_ports: Externalizing logger's config to a user's app. timers: improve code, docstring and type hinting README updates IAW with the above changes Version update: 0.4.0" />
|
|
299
|
+
<option name="LAST_COMMIT_MESSAGE" value="release_ports: Externalizing logger's config to a user's app. timers: improve code, docstring and type hinting README updates IAW with the above changes Version update: 0.4.0" />
|
|
270
300
|
</component>
|
|
271
301
|
</project>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nano_dev_utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
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,16 +24,17 @@ This module provides a `Timer` class for measuring the execution time of code bl
|
|
|
24
24
|
|
|
25
25
|
#### `Timer` Class
|
|
26
26
|
|
|
27
|
-
* **`__init__(self, precision=4, verbose=False)`**: Initializes a `Timer` instance.
|
|
28
|
-
* `precision
|
|
29
|
-
|
|
30
|
-
* `verbose
|
|
31
|
-
|
|
27
|
+
* **`__init__(self, precision: int = 4, verbose: bool = False)`**: Initializes a `Timer` instance.
|
|
28
|
+
* `precision`: The number of decimal places to record and
|
|
29
|
+
display time durations. Defaults to 4.
|
|
30
|
+
* `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs).
|
|
31
|
+
Defaults to `False`.
|
|
32
32
|
|
|
33
|
-
* **`timeit(self, func
|
|
34
|
-
|
|
35
|
-
*
|
|
36
|
-
|
|
33
|
+
* **`timeit(self, func: Callable[P, R]) -> Callable[P, R]`**:
|
|
34
|
+
Decorator that times function execution with automatic unit scaling.
|
|
35
|
+
* When the decorated function is called, this decorator records the start and end times,
|
|
36
|
+
calculates the total execution time, prints the function name and execution
|
|
37
|
+
time (optionally including arguments), and returns the result of the original function.
|
|
37
38
|
|
|
38
39
|
#### Example Usage:
|
|
39
40
|
|
|
@@ -66,7 +67,7 @@ This module provides an `Importer` class for lazy loading and caching module imp
|
|
|
66
67
|
* **`import_mod_from_lib(self, library: str, module_name: str) -> ModuleType | Any`**: Lazily imports a module from a specified library and caches it.
|
|
67
68
|
* `library` (str): The name of the library (e.g., "os", "requests").
|
|
68
69
|
* `module_name` (str): The name of the module to import within the library (e.g., "path", "get").
|
|
69
|
-
* Returns the imported module. If the module has already been imported, it returns
|
|
70
|
+
* Returns the imported module. If the module has already been imported, it returns a cached instance.
|
|
70
71
|
* Raises `ImportError` if the module cannot be found.
|
|
71
72
|
|
|
72
73
|
#### Example Usage:
|
|
@@ -90,34 +91,42 @@ print(f"Imported os.path again (cached): {os_path_again}")
|
|
|
90
91
|
### `release_ports.py`
|
|
91
92
|
|
|
92
93
|
This module provides a `PortsRelease` class to identify and release processes
|
|
93
|
-
listening on specified TCP ports.
|
|
94
|
+
listening on specified TCP ports.
|
|
95
|
+
It supports Windows, Linux, and macOS.
|
|
94
96
|
|
|
95
97
|
#### `PortsRelease` Class
|
|
96
98
|
|
|
97
|
-
* **`__init__(self, default_ports:
|
|
99
|
+
* **`__init__(self, default_ports: list[int] | None = None)`**:
|
|
98
100
|
* Initializes a `PortsRelease` instance.
|
|
99
|
-
* `default_ports
|
|
100
|
-
* If not provided, it defaults to `[6277, 6274]`.
|
|
101
|
+
* `default_ports`: A list of default ports to manage. If not provided, it defaults to `[6277, 6274]`.
|
|
101
102
|
|
|
102
|
-
* **`get_pid_by_port(port: int) ->
|
|
103
|
-
|
|
104
|
-
* commands (`netstat`, `ss`, `lsof`).
|
|
103
|
+
* **`get_pid_by_port(self, port: int) -> int | None`**: A static method that attempts to find
|
|
104
|
+
a process ID (PID) listening on a given `port`.
|
|
105
|
+
* It uses platform-specific commands (`netstat`, `ss`, `lsof`).
|
|
106
|
+
* Returns the PID if found, otherwise `None`.
|
|
105
107
|
|
|
106
|
-
* **`kill_process(pid: int) -> bool`**: A static method that attempts to kill the process
|
|
107
|
-
|
|
108
|
+
* **`kill_process(self, pid: int) -> bool`**: A static method that attempts to kill the process
|
|
109
|
+
with the given `pid`.
|
|
110
|
+
* It uses platform-specific commands (`taskkill`, `kill -9`).
|
|
108
111
|
* Returns `True` if the process was successfully killed, `False` otherwise.
|
|
109
112
|
|
|
110
|
-
* **`release_all(self, ports:
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* For each port, it first tries to get the PID and then attempts to kill the process.
|
|
113
|
+
* **`release_all(self, ports: list[int] | None = None) -> None`**: Releases all processes listening on the specified `ports`.
|
|
114
|
+
* `ports`: A list of ports to release.
|
|
115
|
+
* If `None`, it uses the `default_ports` defined during initialization.
|
|
116
|
+
* For each port, it first tries to get the PID and then attempts to kill the process.
|
|
115
117
|
* It logs the actions and any errors encountered. Invalid port numbers in the provided list are skipped.
|
|
116
118
|
|
|
117
119
|
#### Example Usage:
|
|
118
120
|
|
|
119
121
|
```python
|
|
120
|
-
|
|
122
|
+
import logging
|
|
123
|
+
from nano_dev_utils import PortsRelease
|
|
124
|
+
|
|
125
|
+
# in case you're interested in logging
|
|
126
|
+
logging.basicConfig(filename='port release.log',
|
|
127
|
+
level=logging.INFO, # specify here desire level, e.g. DEBUG etc.
|
|
128
|
+
format='%(asctime)s - %(levelname)s: %(message)s',
|
|
129
|
+
datefmt='%d-%m-%Y %H:%M:%S')
|
|
121
130
|
|
|
122
131
|
# Create an instance with default ports
|
|
123
132
|
port_releaser = PortsRelease()
|
|
@@ -10,16 +10,17 @@ This module provides a `Timer` class for measuring the execution time of code bl
|
|
|
10
10
|
|
|
11
11
|
#### `Timer` Class
|
|
12
12
|
|
|
13
|
-
* **`__init__(self, precision=4, verbose=False)`**: Initializes a `Timer` instance.
|
|
14
|
-
* `precision
|
|
15
|
-
|
|
16
|
-
* `verbose
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* **`timeit(self, func
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
|
|
13
|
+
* **`__init__(self, precision: int = 4, verbose: bool = False)`**: Initializes a `Timer` instance.
|
|
14
|
+
* `precision`: The number of decimal places to record and
|
|
15
|
+
display time durations. Defaults to 4.
|
|
16
|
+
* `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs).
|
|
17
|
+
Defaults to `False`.
|
|
18
|
+
|
|
19
|
+
* **`timeit(self, func: Callable[P, R]) -> Callable[P, R]`**:
|
|
20
|
+
Decorator that times function execution with automatic unit scaling.
|
|
21
|
+
* When the decorated function is called, this decorator records the start and end times,
|
|
22
|
+
calculates the total execution time, prints the function name and execution
|
|
23
|
+
time (optionally including arguments), and returns the result of the original function.
|
|
23
24
|
|
|
24
25
|
#### Example Usage:
|
|
25
26
|
|
|
@@ -52,7 +53,7 @@ This module provides an `Importer` class for lazy loading and caching module imp
|
|
|
52
53
|
* **`import_mod_from_lib(self, library: str, module_name: str) -> ModuleType | Any`**: Lazily imports a module from a specified library and caches it.
|
|
53
54
|
* `library` (str): The name of the library (e.g., "os", "requests").
|
|
54
55
|
* `module_name` (str): The name of the module to import within the library (e.g., "path", "get").
|
|
55
|
-
* Returns the imported module. If the module has already been imported, it returns
|
|
56
|
+
* Returns the imported module. If the module has already been imported, it returns a cached instance.
|
|
56
57
|
* Raises `ImportError` if the module cannot be found.
|
|
57
58
|
|
|
58
59
|
#### Example Usage:
|
|
@@ -76,34 +77,42 @@ print(f"Imported os.path again (cached): {os_path_again}")
|
|
|
76
77
|
### `release_ports.py`
|
|
77
78
|
|
|
78
79
|
This module provides a `PortsRelease` class to identify and release processes
|
|
79
|
-
listening on specified TCP ports.
|
|
80
|
+
listening on specified TCP ports.
|
|
81
|
+
It supports Windows, Linux, and macOS.
|
|
80
82
|
|
|
81
83
|
#### `PortsRelease` Class
|
|
82
84
|
|
|
83
|
-
* **`__init__(self, default_ports:
|
|
85
|
+
* **`__init__(self, default_ports: list[int] | None = None)`**:
|
|
84
86
|
* Initializes a `PortsRelease` instance.
|
|
85
|
-
* `default_ports
|
|
86
|
-
* If not provided, it defaults to `[6277, 6274]`.
|
|
87
|
+
* `default_ports`: A list of default ports to manage. If not provided, it defaults to `[6277, 6274]`.
|
|
87
88
|
|
|
88
|
-
* **`get_pid_by_port(port: int) ->
|
|
89
|
-
|
|
90
|
-
* commands (`netstat`, `ss`, `lsof`).
|
|
89
|
+
* **`get_pid_by_port(self, port: int) -> int | None`**: A static method that attempts to find
|
|
90
|
+
a process ID (PID) listening on a given `port`.
|
|
91
|
+
* It uses platform-specific commands (`netstat`, `ss`, `lsof`).
|
|
92
|
+
* Returns the PID if found, otherwise `None`.
|
|
91
93
|
|
|
92
|
-
* **`kill_process(pid: int) -> bool`**: A static method that attempts to kill the process
|
|
93
|
-
|
|
94
|
+
* **`kill_process(self, pid: int) -> bool`**: A static method that attempts to kill the process
|
|
95
|
+
with the given `pid`.
|
|
96
|
+
* It uses platform-specific commands (`taskkill`, `kill -9`).
|
|
94
97
|
* Returns `True` if the process was successfully killed, `False` otherwise.
|
|
95
98
|
|
|
96
|
-
* **`release_all(self, ports:
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* For each port, it first tries to get the PID and then attempts to kill the process.
|
|
99
|
+
* **`release_all(self, ports: list[int] | None = None) -> None`**: Releases all processes listening on the specified `ports`.
|
|
100
|
+
* `ports`: A list of ports to release.
|
|
101
|
+
* If `None`, it uses the `default_ports` defined during initialization.
|
|
102
|
+
* For each port, it first tries to get the PID and then attempts to kill the process.
|
|
101
103
|
* It logs the actions and any errors encountered. Invalid port numbers in the provided list are skipped.
|
|
102
104
|
|
|
103
105
|
#### Example Usage:
|
|
104
106
|
|
|
105
107
|
```python
|
|
106
|
-
|
|
108
|
+
import logging
|
|
109
|
+
from nano_dev_utils import PortsRelease
|
|
110
|
+
|
|
111
|
+
# in case you're interested in logging
|
|
112
|
+
logging.basicConfig(filename='port release.log',
|
|
113
|
+
level=logging.INFO, # specify here desire level, e.g. DEBUG etc.
|
|
114
|
+
format='%(asctime)s - %(levelname)s: %(message)s',
|
|
115
|
+
datefmt='%d-%m-%Y %H:%M:%S')
|
|
107
116
|
|
|
108
117
|
# Create an instance with default ports
|
|
109
118
|
port_releaser = PortsRelease()
|
|
@@ -2,12 +2,8 @@ import platform
|
|
|
2
2
|
import subprocess
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
logging.basicConfig(filename='port release.log',
|
|
7
|
-
level=logging.INFO,
|
|
8
|
-
format='%(asctime)s - %(levelname)s: %(message)s',
|
|
9
|
-
datefmt='%d-%m-%Y %H:%M:%S')
|
|
10
5
|
lgr = logging.getLogger(__name__)
|
|
6
|
+
"""Module-level logger. Configure using logging.basicConfig() in your application."""
|
|
11
7
|
|
|
12
8
|
PROXY_SERVER = 6277
|
|
13
9
|
INSPECTOR_CLIENT = 6274
|
|
@@ -152,5 +148,4 @@ class PortsRelease:
|
|
|
152
148
|
else:
|
|
153
149
|
lgr.error(self._log_terminate_failed(pid=pid, port=port))
|
|
154
150
|
except Exception as e:
|
|
155
|
-
lgr.error(self._log_unexpected_error(e))
|
|
156
|
-
|
|
151
|
+
lgr.error(self._log_unexpected_error(e))
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
import time
|
|
3
|
+
from typing import Callable, ParamSpec, TypeVar
|
|
4
|
+
P = ParamSpec('P')
|
|
5
|
+
R = TypeVar('R')
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Timer:
|
|
9
|
+
def __init__(self, precision=4, verbose=False):
|
|
10
|
+
self.precision = precision
|
|
11
|
+
self.verbose = verbose
|
|
12
|
+
self.units = [
|
|
13
|
+
(1e9, 's'),
|
|
14
|
+
(1e6, 'ms'),
|
|
15
|
+
(1e3, 'μs'),
|
|
16
|
+
(1.0, 'ns')
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
def timeit(self, func: Callable[P, R]) -> Callable[P, R]:
|
|
20
|
+
"""Decorator that times function execution with automatic unit scaling."""
|
|
21
|
+
@wraps(func)
|
|
22
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
23
|
+
start = time.perf_counter_ns()
|
|
24
|
+
result = func(*args, **kwargs)
|
|
25
|
+
elapsed = time.perf_counter_ns() - start
|
|
26
|
+
|
|
27
|
+
value = elapsed
|
|
28
|
+
unit = 'ns'
|
|
29
|
+
|
|
30
|
+
for divisor, unit in self.units:
|
|
31
|
+
if elapsed >= divisor or unit == 'ns':
|
|
32
|
+
value = elapsed / divisor
|
|
33
|
+
break
|
|
34
|
+
|
|
35
|
+
extra_info = f'{args} {kwargs} ' if self.verbose else ''
|
|
36
|
+
print(f'{func.__name__} {extra_info}took {value:.{self.precision}f} [{unit}]')
|
|
37
|
+
return result
|
|
38
|
+
|
|
39
|
+
return wrapper
|
|
@@ -173,12 +173,13 @@ class TestPortsRelease(unittest.TestCase):
|
|
|
173
173
|
|
|
174
174
|
def test_get_pid_by_port_unexpected_exception(self):
|
|
175
175
|
with patch('platform.system', return_value='Linux'):
|
|
176
|
-
|
|
176
|
+
err = Exception("Unexpected")
|
|
177
|
+
with patch('subprocess.Popen', side_effect=err):
|
|
177
178
|
port = 1234
|
|
178
179
|
pid = self.ports_release.get_pid_by_port(port)
|
|
179
180
|
self.assertIsNone(pid)
|
|
180
|
-
self.mock_logger.error.assert_called_once_with(
|
|
181
|
-
|
|
181
|
+
self.mock_logger.error.assert_called_once_with(f'An unexpected '
|
|
182
|
+
f'error occurred: {err}')
|
|
182
183
|
|
|
183
184
|
def test_kill_process_success(self):
|
|
184
185
|
with patch('platform.system', return_value='Linux'):
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
from functools import wraps
|
|
2
|
-
import time
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Timer:
|
|
6
|
-
def __init__(self, precision=4, verbose=False):
|
|
7
|
-
self.precision = precision
|
|
8
|
-
self.verbose = verbose
|
|
9
|
-
|
|
10
|
-
def timeit(self, func):
|
|
11
|
-
@wraps(func)
|
|
12
|
-
def timeit_wrapper(*args, **kwargs):
|
|
13
|
-
start_time = time.perf_counter_ns()
|
|
14
|
-
result = func(*args, **kwargs)
|
|
15
|
-
end_time = time.perf_counter_ns()
|
|
16
|
-
total_ns = end_time - start_time
|
|
17
|
-
|
|
18
|
-
if total_ns < 1_000: # 1μs
|
|
19
|
-
value = total_ns
|
|
20
|
-
unit = "ns"
|
|
21
|
-
elif total_ns < 1_000_000: # < 1ms
|
|
22
|
-
value = total_ns / 1_000
|
|
23
|
-
unit = "μs"
|
|
24
|
-
elif total_ns < 1_000_000_000: # < 1s
|
|
25
|
-
value = total_ns / 1_000_000
|
|
26
|
-
unit = "ms"
|
|
27
|
-
else:
|
|
28
|
-
value = total_ns / 1_000_000_000
|
|
29
|
-
unit = "s"
|
|
30
|
-
|
|
31
|
-
extra_info = f'{args} {kwargs} ' if self.verbose else ''
|
|
32
|
-
print(f'{func.__name__} {extra_info}took {value:.{self.precision}f} [{unit}]')
|
|
33
|
-
return result
|
|
34
|
-
|
|
35
|
-
return timeit_wrapper
|
|
File without changes
|
|
File without changes
|
{nano_dev_utils-0.3.4 → nano_dev_utils-0.4.1}/.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
|