nano-dev-utils 1.4.0__py3-none-any.whl → 1.5.2__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.

@@ -1,270 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: nano_dev_utils
3
- Version: 1.4.0
4
- Summary: A collection of small Python utilities for developers.
5
- Project-URL: Homepage, https://github.com/yaronday/nano_utils
6
- Project-URL: Issues, https://github.com/yaronday/nano_utils/issues
7
- Project-URL: license, https://github.com/yaronday/nano_dev_utils/blob/master/LICENSE
8
- Author-email: Yaron Dayan <yaronday77@gmail.com>
9
- License: MIT
10
- License-File: LICENSE
11
- Classifier: Operating System :: OS Independent
12
- Classifier: Programming Language :: Python :: 3
13
- Requires-Python: >=3.10
14
- Requires-Dist: build>=1.3.0
15
- Description-Content-Type: text/markdown
16
-
17
- # nano_dev_utils
18
-
19
- A collection of small Python utilities for developers.
20
-
21
- ## Modules
22
-
23
- ### `timers.py`
24
-
25
- 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.
26
-
27
- #### `Timer` Class
28
-
29
- * **`__init__(self, precision: int = 4, verbose: bool = False)`**: Initializes a `Timer` instance.
30
- * `precision`: The number of decimal places to record and display time durations. Defaults to 4.
31
- * `verbose`: Optionally displays the function's positional arguments (args) and keyword arguments (kwargs). Defaults to `False`.
32
-
33
- * **`def timeit(
34
- self,
35
- iterations: int = 1,
36
- timeout: float | None = None,
37
- per_iteration: bool = False,
38
- ) -> Callable[[Callable[P, Any]], Callable[P, Any]]:`**:
39
- Decorator that times either **sync** or **async** function execution with advanced features:
40
- * `iterations`: Number of times to run the function (for averaging). Defaults to 1.
41
- * `timeout`: Maximum allowed execution time in seconds. When exceeded:
42
- * Raises `TimeoutError` immediately
43
- * **Warning:** The function execution will be aborted mid-operation
44
- * No return value will be available if timeout occurs
45
- * `per_iteration`: If True, applies timeout check to each iteration; otherwise checks total time across all iterations.
46
- * Features:
47
- * Records execution times
48
- * Handles timeout conditions
49
- * Calculates average execution time across iterations
50
- * Prints the function name and execution time (with optional arguments)
51
- * Returns the result of the original function (unless timeout occurs)
52
-
53
- #### Example Usage:
54
-
55
- ```python
56
- import time
57
- from nano_dev_utils import timer
58
-
59
- # Basic timing
60
- @timer.timeit()
61
- def my_function(a, b=10):
62
- """A sample function."""
63
- time.sleep(0.1)
64
- return a + b
65
-
66
- timer.init(precision=6, verbose=True)
67
- '''
68
- Alternatively we could have used the `update` method as well:
69
-
70
- timer.update({'precision': 6, 'verbose': True})
71
-
72
- The above config could be also achieved via explicit instantiation:
73
-
74
- from nano_dev_utils.timers import Timer
75
- timer = Timer(precision=6, verbose=True)
76
- '''
77
-
78
- # Advanced usage with timeout and iterations
79
- @timer.timeit(iterations=5, timeout=0.5, per_iteration=True)
80
- def critical_function(x):
81
- """Function with timeout check per iteration."""
82
- time.sleep(0.08)
83
- return x * 2
84
-
85
- result1 = my_function(5, b=20) # Shows args/kwargs and timing
86
- result2 = critical_function(10) # Runs 5 times with per-iteration timeout
87
- ```
88
-
89
- ### `dynamic_importer.py`
90
-
91
- This module provides an `Importer` class for lazy loading and caching module imports.
92
-
93
- #### `Importer` Class
94
-
95
- * **`__init__(self)`**: Initializes an `Importer` instance with an empty dictionary `imported_modules` to cache imported modules.
96
-
97
- * **`import_mod_from_lib(self, library: str, module_name: str) -> ModuleType | Any`**: Lazily imports a module from a specified library and caches it.
98
- * `library` (str): The name of the library (e.g., "os", "requests").
99
- * `module_name` (str): The name of the module to import within the library (e.g., "path", "get").
100
- * Returns the imported module. If the module has already been imported, it returns a cached instance.
101
- * Raises `ImportError` if the module cannot be found.
102
-
103
- #### Example Usage:
104
-
105
- ```python
106
- from nano_dev_utils import importer
107
-
108
- os_path = importer.import_mod_from_lib("os", "path")
109
- print(f"Imported os.path: {os_path}")
110
-
111
- requests_get = importer.import_mod_from_lib("requests", "get")
112
- print(f"Imported requests.get: {requests_get}")
113
-
114
- # Subsequent calls will return the cached module
115
- os_path_again = importer.import_mod_from_lib("os", "path")
116
- print(f"Imported os.path again (cached): {os_path_again}")
117
- ```
118
-
119
- ### `release_ports.py`
120
-
121
- This module provides a `PortsRelease` class to identify and release processes
122
- listening on specified TCP ports.
123
- It supports Windows, Linux, and macOS.
124
-
125
- #### `PortsRelease` Class
126
-
127
- * **`__init__(self, default_ports: list[int] | None = None)`**:
128
- * Initializes a `PortsRelease` instance.
129
- * `default_ports`: A list of default ports to manage. If not provided, it defaults to `[6277, 6274]`.
130
-
131
- * **`get_pid_by_port(self, port: int) -> int | None`**: A static method that attempts to find
132
- a process ID (PID) listening on a given `port`.
133
- * It uses platform-specific commands (`netstat`, `ss`, `lsof`).
134
- * Returns the PID if found, otherwise `None`.
135
-
136
- * **`kill_process(self, pid: int) -> bool`**: A static method that attempts to kill the process
137
- with the given `pid`.
138
- * It uses platform-specific commands (`taskkill`, `kill -9`).
139
- * Returns `True` if the process was successfully killed, `False` otherwise.
140
-
141
- * **`release_all(self, ports: list[int] | None = None) -> None`**: Releases all processes listening on the specified `ports`.
142
- * `ports`: A list of ports to release.
143
- * If `None`, it uses the `default_ports` defined during initialization.
144
- * For each port, it first tries to get the PID and then attempts to kill the process.
145
- * It logs the actions and any errors encountered. Invalid port numbers in the provided list are skipped.
146
-
147
- #### Example Usage:
148
-
149
- ```python
150
- import logging
151
- from nano_dev_utils import ports_release, PortsRelease
152
-
153
-
154
- # For configuration of logging level and format (supported already):
155
- logging.basicConfig(filename='port release.log',
156
- level=logging.INFO, # DEBUG, WARNING, ERROR, CRITICAL
157
- format='%(asctime)s - %(levelname)s: %(message)s',
158
- datefmt='%d-%m-%Y %H:%M:%S')
159
-
160
-
161
- ports_release.release_all()
162
-
163
- # Create an instance with custom ports
164
- custom_ports_releaser = PortsRelease(default_ports=[8080, 9000, 6274])
165
- custom_ports_releaser.release_all(ports=[8080, 9000])
166
-
167
- # Release only the default ports
168
- ports_release.release_all()
169
- ```
170
-
171
- ### `file_tree_display.py`
172
-
173
- This module provides a class-based utility for generating a visually structured directory tree.
174
- It supports recursive traversal, customizable hierarchy styles, and exclusion patterns for directories and files.
175
- Output can be displayed in the console or saved to a file.
176
-
177
-
178
- #### Key Features
179
-
180
- - Recursively displays and logs directory trees
181
- - Efficient directory traversal
182
- - Blazing fast (see Benchmarks below)
183
- - Generates human-readable file tree structure
184
- - Customizable tree display output
185
- - Optionally saves the resulting tree to a text file
186
- - Supports ignoring specific directories or files via pattern matching
187
- - Handles permission and read/write errors gracefully
188
-
189
- ## Benchmarks
190
-
191
- As measured on a dataset of 10553 files, 1235 folders (ca. 16 GB) using Python 3.10 on SSD.
192
- Avg. time was measured over 10 runs per configuration.
193
-
194
- | Tool | Time (s) |
195
- |-----------------|----------|
196
- | FileTreeDisplay | 0.198 |
197
- | Seedir | 4.378 |
198
-
199
-
200
-
201
- #### Class Overview
202
-
203
- **`FileTreeDisplay`**
204
- Constructs and manages the visual representation of a directory structure.
205
-
206
- **Initialization Parameters**
207
-
208
- | Parameter | Type | Description |
209
- |:---------------------------|:--------------------------------|:----------------------------------------------------------------------------|
210
- | `root_dir` | `str` | Path to the directory to scan. |
211
- | `filepath` | `str / None` | Optional output destination for the saved file tree. |
212
- | `ignore_dirs` | `list[str] or set[str] or None` | Directory names or patterns to skip. |
213
- | `ignore_files` | `list[str] or set[str] or None` | File names or patterns to skip. |
214
- | `include_dirs` | `list[str] or set[str] or None` | Only include specified folder names or patterns. |
215
- | `include_files` | `list[str] or set[str] or None` | Only include specified file names or patterns, '*.pdf' - only include pdfs. |
216
- | `style` | `str` | Character(s) used to mark hierarchy levels. Defaults to `' '`. |
217
- | `indent` | `int` | Number of style characters per level. Defaults `2`. |
218
- | `files_first` | `bool` | Determines whether to list files first. Defaults to False. |
219
- | `sort_key_name` | `str` | Sort key. 'lex' (lexicographic) or 'custom'. Defaults to 'natural'. |
220
- | `reverse` | `bool` | Reversed sorting order. |
221
- | `custom_sort` | `Callable[[str], Any] / None` | Custom sort key function. |
222
- | `title` | `str` | Custom title shown in the output. |
223
- | `save2file` | `bool` | Save file tree (folder structure) info into a file. |
224
- | `printout` | `bool` | Print file tree info. |
225
-
226
- #### Core Methods
227
-
228
- - `file_tree_display(save2file: bool = True) -> str | None`
229
- Generates the directory tree. If `save2file=True`, saves the output; otherwise prints it directly.
230
- - `build_tree(dir_path: str, prefix: str = '') -> Generator[str, None, None]`
231
- Recursively yields formatted lines representing directories and files.
232
-
233
-
234
- #### Example Usage
235
-
236
- ```python
237
- from pathlib import Path
238
- from nano_dev_utils.file_tree_display import FileTreeDisplay
239
-
240
- root = r'c:/your_root_dir'
241
- target_path = r'c:/your_target_path'
242
- filename = 'filetree.md'
243
- filepath = str(Path(target_path, filename))
244
-
245
- ftd = FileTreeDisplay(root_dir=root,
246
- ignore_dirs=['.git', 'node_modules', '.idea'],
247
- ignore_files={'.gitignore', '*.toml'}, style='—',
248
- include_dirs=['src', 'tests', 'snapshots'],
249
- filepath=filepath,
250
- sort_key_name='custom',
251
- custom_sort=(lambda x: any(ext in x.lower() for ext in ('jpg', 'png'))),
252
- reverse=True
253
- )
254
- ftd.file_tree_display()
255
- ```
256
-
257
-
258
- #### Error Handling
259
-
260
- The module raises well-defined exceptions for common issues:
261
-
262
- - `NotADirectoryError` when the path is not a directory
263
- - `PermissionError` for unreadable directories or write-protected files
264
- - `OSError` for general I/O or write failures
265
-
266
- ***
267
-
268
- ## License
269
- This project is licensed under the MIT License.
270
- See [LICENSE](LICENSE) for details.
@@ -1,10 +0,0 @@
1
- nano_dev_utils/__init__.py,sha256=bJNCUyssMVyNmOey-god8A2kElC4nCR9B5DsdvUrKWw,1014
2
- nano_dev_utils/common.py,sha256=bNgiaBP5kQUxfEUN3HYp1_TnwG-SRvsiqu67yAG5Y4o,5585
3
- nano_dev_utils/dynamic_importer.py,sha256=-Mh76366lI_mP2QA_jxiVfcKCHOHeukS_j4v7fTh0xw,1028
4
- nano_dev_utils/file_tree_display.py,sha256=0pfDr1QgyPJZbtl8mKNfJO0T3Jl2vUrwt8syVn_PhsI,8192
5
- nano_dev_utils/release_ports.py,sha256=yLWMMbN6j6kWtGTg-Nynn37-Q4b2rxkls9hs2sqeZjA,6081
6
- nano_dev_utils/timers.py,sha256=Ko2RR96-Sb6hIQAPxiwCUPAK2uwJ1dP_9Teym8lx_lo,7350
7
- nano_dev_utils-1.4.0.dist-info/METADATA,sha256=z4PfsxOWteGXmLuJS5MtivqCKox9LR6wUKTjhelw9_c,11642
8
- nano_dev_utils-1.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- nano_dev_utils-1.4.0.dist-info/licenses/LICENSE,sha256=Muenl7Bw_LdtHZtlOMAP7Kt97gDCq8WWp2605eDWhHU,1089
10
- nano_dev_utils-1.4.0.dist-info/RECORD,,