chutils 2.6.1__tar.gz → 2.7.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.
- chutils-2.6.1/README.md → chutils-2.7.1/PKG-INFO +127 -1
- chutils-2.6.1/PKG-INFO → chutils-2.7.1/README.md +74 -33
- {chutils-2.6.1 → chutils-2.7.1}/pyproject.toml +23 -2
- chutils-2.7.1/src/chutils/__init__.py +184 -0
- chutils-2.7.1/src/chutils/__init__.pyi +226 -0
- chutils-2.7.1/src/chutils/cache/__init__.py +5 -0
- chutils-2.7.1/src/chutils/cache/base.py +85 -0
- chutils-2.7.1/src/chutils/cache/decorator.py +93 -0
- chutils-2.7.1/src/chutils/cache/in_memory.py +70 -0
- chutils-2.7.1/src/chutils/cache/utils.py +51 -0
- chutils-2.7.1/src/chutils/cli.py +57 -0
- chutils-2.7.1/src/chutils/cli_booster.py +151 -0
- chutils-2.7.1/src/chutils/cli_utils.py +95 -0
- chutils-2.7.1/src/chutils/commands/__init__.py +29 -0
- chutils-2.7.1/src/chutils/commands/base.py +39 -0
- chutils-2.7.1/src/chutils/commands/config.py +123 -0
- chutils-2.7.1/src/chutils/commands/dev.py +162 -0
- chutils-2.7.1/src/chutils/commands/init.py +135 -0
- chutils-2.7.1/src/chutils/commands/paths.py +78 -0
- chutils-2.7.1/src/chutils/commands/secrets.py +81 -0
- chutils-2.7.1/src/chutils/commands/template.py +92 -0
- chutils-2.7.1/src/chutils/commands/utils.py +24 -0
- chutils-2.7.1/src/chutils/commands/validate.py +76 -0
- chutils-2.7.1/src/chutils/config/GEMINI.md +23 -0
- chutils-2.7.1/src/chutils/config/__init__.py +222 -0
- chutils-2.7.1/src/chutils/config/core.py +273 -0
- chutils-2.7.1/src/chutils/config/diagnostics.py +128 -0
- chutils-2.7.1/src/chutils/config/generator.py +134 -0
- chutils-2.7.1/src/chutils/config/getters.py +280 -0
- chutils-2.7.1/src/chutils/config/manager.py +435 -0
- chutils-2.7.1/src/chutils/config/providers.py +459 -0
- chutils-2.7.1/src/chutils/config/schema.py +114 -0
- {chutils-2.6.1 → chutils-2.7.1}/src/chutils/config/utils.py +27 -11
- {chutils-2.6.1 → chutils-2.7.1}/src/chutils/config/watcher.py +16 -12
- {chutils-2.6.1 → chutils-2.7.1}/src/chutils/context.py +13 -0
- {chutils-2.6.1 → chutils-2.7.1}/src/chutils/decorators.py +14 -4
- chutils-2.7.1/src/chutils/dev/__init__.py +3 -0
- chutils-2.7.1/src/chutils/dev/ast_indexer.py +279 -0
- chutils-2.7.1/src/chutils/dev/models.py +64 -0
- chutils-2.7.1/src/chutils/exceptions.py +86 -0
- chutils-2.7.1/src/chutils/features.py +187 -0
- chutils-2.7.1/src/chutils/fs.py +130 -0
- chutils-2.7.1/src/chutils/lifecycle.py +199 -0
- chutils-2.7.1/src/chutils/logger/GEMINI.md +21 -0
- chutils-2.7.1/src/chutils/logger/__init__.py +38 -0
- chutils-2.6.1/src/chutils/logger.py → chutils-2.7.1/src/chutils/logger/core.py +157 -297
- chutils-2.7.1/src/chutils/logger/formatters.py +48 -0
- chutils-2.7.1/src/chutils/logger/handlers.py +124 -0
- chutils-2.7.1/src/chutils/logger/masking.py +102 -0
- chutils-2.7.1/src/chutils/secret_manager/GEMINI.md +20 -0
- chutils-2.7.1/src/chutils/secret_manager/__init__.py +10 -0
- chutils-2.7.1/src/chutils/secret_manager/core.py +189 -0
- chutils-2.7.1/src/chutils/secret_manager/providers.py +249 -0
- chutils-2.7.1/src/chutils/testing/__init__.py +11 -0
- chutils-2.7.1/src/chutils/testing/fixtures.py +205 -0
- chutils-2.7.1/src/chutils/time.py +202 -0
- chutils-2.7.1/src/chutils/tracing.py +187 -0
- chutils-2.6.1/src/chutils/__init__.py +0 -127
- chutils-2.6.1/src/chutils/cli.py +0 -71
- chutils-2.6.1/src/chutils/config/__init__.py +0 -647
- chutils-2.6.1/src/chutils/config/manager.py +0 -98
- chutils-2.6.1/src/chutils/config/providers.py +0 -234
- chutils-2.6.1/src/chutils/secret_manager.py +0 -338
- {chutils-2.6.1 → chutils-2.7.1}/LICENSE +0 -0
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chutils
|
|
3
|
+
Version: 2.7.1
|
|
4
|
+
Summary: Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Author: Chu4hel
|
|
8
|
+
Author-email: sergeiivanov636@gmail.com
|
|
9
|
+
Requires-Python: >=3.9, !=3.9.0, !=3.9.1
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Provides-Extra: date
|
|
17
|
+
Provides-Extra: full
|
|
18
|
+
Provides-Extra: json
|
|
19
|
+
Provides-Extra: otel
|
|
20
|
+
Provides-Extra: pydantic
|
|
21
|
+
Provides-Extra: rich
|
|
22
|
+
Provides-Extra: secrets
|
|
23
|
+
Provides-Extra: testing
|
|
24
|
+
Provides-Extra: watch
|
|
25
|
+
Requires-Dist: keyring (>=25.7.0)
|
|
26
|
+
Requires-Dist: keyring (>=25.7.0) ; extra == "full"
|
|
27
|
+
Requires-Dist: keyring (>=25.7.0) ; extra == "secrets"
|
|
28
|
+
Requires-Dist: opentelemetry-api (>=1.41.1) ; extra == "full"
|
|
29
|
+
Requires-Dist: opentelemetry-api (>=1.41.1) ; extra == "otel"
|
|
30
|
+
Requires-Dist: opentelemetry-exporter-otlp (>=1.41.1) ; extra == "full"
|
|
31
|
+
Requires-Dist: opentelemetry-exporter-otlp (>=1.41.1) ; extra == "otel"
|
|
32
|
+
Requires-Dist: opentelemetry-sdk (>=1.41.1) ; extra == "full"
|
|
33
|
+
Requires-Dist: opentelemetry-sdk (>=1.41.1) ; extra == "otel"
|
|
34
|
+
Requires-Dist: pydantic (>=2.13.4) ; extra == "full"
|
|
35
|
+
Requires-Dist: pydantic (>=2.13.4,<3.0.0) ; extra == "pydantic"
|
|
36
|
+
Requires-Dist: pytest (>=8.0.0) ; (python_full_version < "3.10.0") and (extra == "full")
|
|
37
|
+
Requires-Dist: pytest (>=8.0.0) ; (python_full_version < "3.10.0") and (extra == "testing")
|
|
38
|
+
Requires-Dist: pytest (>=9.0.3) ; (python_full_version >= "3.10.0") and (extra == "full")
|
|
39
|
+
Requires-Dist: pytest (>=9.0.3) ; (python_full_version >= "3.10.0") and (extra == "testing")
|
|
40
|
+
Requires-Dist: python-dateutil (>=2.9.0) ; extra == "date"
|
|
41
|
+
Requires-Dist: python-dateutil (>=2.9.0) ; extra == "full"
|
|
42
|
+
Requires-Dist: python-dotenv (>=1.2.1) ; python_full_version < "3.10.0"
|
|
43
|
+
Requires-Dist: python-dotenv (>=1.2.2) ; python_full_version >= "3.10.0"
|
|
44
|
+
Requires-Dist: python-json-logger (>=3.2.1) ; extra == "full"
|
|
45
|
+
Requires-Dist: python-json-logger (>=3.2.1) ; extra == "json"
|
|
46
|
+
Requires-Dist: pyyaml (>=6.0.3)
|
|
47
|
+
Requires-Dist: rich (>=15.0.0) ; extra == "full"
|
|
48
|
+
Requires-Dist: rich (>=15.0.0) ; extra == "rich"
|
|
49
|
+
Requires-Dist: watchdog (>=6.0.0) ; extra == "full"
|
|
50
|
+
Requires-Dist: watchdog (>=6.0.0) ; extra == "watch"
|
|
51
|
+
Description-Content-Type: text/markdown
|
|
52
|
+
|
|
1
53
|
[Русская версия](docs/README_RU.md)
|
|
2
54
|
|
|
3
55
|
# chutils: Stop the Routine!
|
|
@@ -34,6 +86,12 @@ Every time you start a new project, you have to solve the same tasks:
|
|
|
34
86
|
box. It returns a custom logger with additional debug levels (`devdebug`, `mediumdebug`).
|
|
35
87
|
- **🔒 Secure Secret Storage:** The `secret_manager` module provides a simple interface for saving and retrieving secrets
|
|
36
88
|
via the system `keyring`, with a fallback to `.env` files.
|
|
89
|
+
- **🚀 CLI Booster:** Turn any function into a CLI tool in seconds using the `@cli_command` decorator with automatic type
|
|
90
|
+
mapping and docstring parsing.
|
|
91
|
+
- **⏰ Painless Datetime:** Always-aware UTC time utilities, smart parsing, and human-readable time intervals.
|
|
92
|
+
- **📡 Distributed Tracing:** Seamless OpenTelemetry integration with `@trace` decorator and automatic log correlation.
|
|
93
|
+
- **🔍 Config Diagnostics:** Interactive trace of configuration sources and priorities via `config debug` command.
|
|
94
|
+
- **🌐 Remote Configuration:** Load settings from HTTP/HTTPS endpoints with background polling and fallback support.
|
|
37
95
|
- **🔄 Hot-Reload:** Support for automatic configuration reloading on file changes without restart (requires
|
|
38
96
|
`pip install chutils[watch]`).
|
|
39
97
|
- **⚡ Async Ready:** Most core functions have asynchronous versions (prefixed with `a`) for non-blocking execution.
|
|
@@ -249,8 +307,15 @@ In environments like Docker or CI/CD where `keyring` is unavailable, you can sup
|
|
|
249
307
|
- `@log_function_details`: Logs arguments, execution time, and result (uses `DEVDEBUG` level).
|
|
250
308
|
- `@timeout(seconds, fallback)`: Limits function execution time. Supports sync/async and optional fallback.
|
|
251
309
|
- `@retry`: Automatically retries a function if it fails. Supports sync/async, backoff, jitter, and exception filtering.
|
|
310
|
+
- `@cli_command`: Turns any function into a standalone CLI script with automatic argument parsing.
|
|
311
|
+
|
|
312
|
+
### Time & Dates (`chutils.time`)
|
|
313
|
+
|
|
314
|
+
- `utc_now()`: Returns a timezone-aware UTC datetime.
|
|
315
|
+
- `parse_datetime(value)`: Smart parsing of strings and timestamps into UTC.
|
|
316
|
+
- `humanize_timedelta(dt)`: Returns human-readable strings like "5 minutes ago" or "tomorrow".
|
|
252
317
|
|
|
253
|
-
|
|
318
|
+
### Example of @retry usage:
|
|
254
319
|
|
|
255
320
|
```python
|
|
256
321
|
from chutils.decorators import retry
|
|
@@ -262,6 +327,67 @@ def fetch_data():
|
|
|
262
327
|
...
|
|
263
328
|
```
|
|
264
329
|
|
|
330
|
+
## Command Line Interface (CLI)
|
|
331
|
+
|
|
332
|
+
`chutils` includes a set of tools to speed up development and debugging.
|
|
333
|
+
|
|
334
|
+
### 1. Initialize Project
|
|
335
|
+
|
|
336
|
+
Quickly set up a new project with a default configuration and `.gitignore` rules:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Interactive mode
|
|
340
|
+
chutils init
|
|
341
|
+
|
|
342
|
+
# Non-interactive mode (default values)
|
|
343
|
+
chutils init -y
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### 2. Validate Configuration
|
|
347
|
+
|
|
348
|
+
Check if your configuration files match your Pydantic models:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
# Automatically finds 'Settings' class in context.py or config.py
|
|
352
|
+
chutils validate
|
|
353
|
+
|
|
354
|
+
# Explicitly specify the model path
|
|
355
|
+
chutils validate --model src.settings:AppConfig
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 3. Debug Search Paths
|
|
359
|
+
|
|
360
|
+
See exactly where `chutils` is looking for configuration files:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Human-readable output
|
|
364
|
+
chutils show-paths
|
|
365
|
+
|
|
366
|
+
# JSON output for automation
|
|
367
|
+
chutils show-paths --json
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### 4. Manage Secrets
|
|
371
|
+
|
|
372
|
+
Manage your system keyring secrets directly from the terminal:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# Set a secret
|
|
376
|
+
chutils secrets set API_KEY "your-secret-value" --service my_app
|
|
377
|
+
|
|
378
|
+
# Delete a secret
|
|
379
|
+
chutils secrets delete API_KEY --service my_app
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 5. Debug Configuration
|
|
383
|
+
|
|
384
|
+
Trace exactly where each configuration value comes from:
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
chutils config debug
|
|
388
|
+
```
|
|
389
|
+
|
|
265
390
|
## License
|
|
266
391
|
|
|
267
392
|
The project is distributed under the MIT License.
|
|
393
|
+
|
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: chutils
|
|
3
|
-
Version: 2.6.1
|
|
4
|
-
Summary: Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах.
|
|
5
|
-
License-Expression: MIT
|
|
6
|
-
License-File: LICENSE
|
|
7
|
-
Author: Chu4hel
|
|
8
|
-
Author-email: sergeiivanov636@gmail.com
|
|
9
|
-
Requires-Python: >=3.9, !=3.9.0, !=3.9.1
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
-
Provides-Extra: full
|
|
17
|
-
Provides-Extra: json
|
|
18
|
-
Provides-Extra: pydantic
|
|
19
|
-
Provides-Extra: watch
|
|
20
|
-
Requires-Dist: keyring (>=25.7.0)
|
|
21
|
-
Requires-Dist: pydantic (>=2.13.4) ; extra == "full"
|
|
22
|
-
Requires-Dist: pydantic (>=2.13.4,<3.0.0) ; extra == "pydantic"
|
|
23
|
-
Requires-Dist: python-dotenv (>=1.2.1) ; python_full_version < "3.10.0"
|
|
24
|
-
Requires-Dist: python-dotenv (>=1.2.2) ; python_full_version >= "3.10.0"
|
|
25
|
-
Requires-Dist: python-json-logger (>=3.2.1) ; extra == "full"
|
|
26
|
-
Requires-Dist: python-json-logger (>=3.2.1) ; extra == "json"
|
|
27
|
-
Requires-Dist: pyyaml (>=6.0.3)
|
|
28
|
-
Requires-Dist: watchdog (>=6.0.0) ; extra == "full"
|
|
29
|
-
Requires-Dist: watchdog (>=6.0.0) ; extra == "watch"
|
|
30
|
-
Description-Content-Type: text/markdown
|
|
31
|
-
|
|
32
1
|
[Русская версия](docs/README_RU.md)
|
|
33
2
|
|
|
34
3
|
# chutils: Stop the Routine!
|
|
@@ -65,6 +34,12 @@ Every time you start a new project, you have to solve the same tasks:
|
|
|
65
34
|
box. It returns a custom logger with additional debug levels (`devdebug`, `mediumdebug`).
|
|
66
35
|
- **🔒 Secure Secret Storage:** The `secret_manager` module provides a simple interface for saving and retrieving secrets
|
|
67
36
|
via the system `keyring`, with a fallback to `.env` files.
|
|
37
|
+
- **🚀 CLI Booster:** Turn any function into a CLI tool in seconds using the `@cli_command` decorator with automatic type
|
|
38
|
+
mapping and docstring parsing.
|
|
39
|
+
- **⏰ Painless Datetime:** Always-aware UTC time utilities, smart parsing, and human-readable time intervals.
|
|
40
|
+
- **📡 Distributed Tracing:** Seamless OpenTelemetry integration with `@trace` decorator and automatic log correlation.
|
|
41
|
+
- **🔍 Config Diagnostics:** Interactive trace of configuration sources and priorities via `config debug` command.
|
|
42
|
+
- **🌐 Remote Configuration:** Load settings from HTTP/HTTPS endpoints with background polling and fallback support.
|
|
68
43
|
- **🔄 Hot-Reload:** Support for automatic configuration reloading on file changes without restart (requires
|
|
69
44
|
`pip install chutils[watch]`).
|
|
70
45
|
- **⚡ Async Ready:** Most core functions have asynchronous versions (prefixed with `a`) for non-blocking execution.
|
|
@@ -280,8 +255,15 @@ In environments like Docker or CI/CD where `keyring` is unavailable, you can sup
|
|
|
280
255
|
- `@log_function_details`: Logs arguments, execution time, and result (uses `DEVDEBUG` level).
|
|
281
256
|
- `@timeout(seconds, fallback)`: Limits function execution time. Supports sync/async and optional fallback.
|
|
282
257
|
- `@retry`: Automatically retries a function if it fails. Supports sync/async, backoff, jitter, and exception filtering.
|
|
258
|
+
- `@cli_command`: Turns any function into a standalone CLI script with automatic argument parsing.
|
|
259
|
+
|
|
260
|
+
### Time & Dates (`chutils.time`)
|
|
261
|
+
|
|
262
|
+
- `utc_now()`: Returns a timezone-aware UTC datetime.
|
|
263
|
+
- `parse_datetime(value)`: Smart parsing of strings and timestamps into UTC.
|
|
264
|
+
- `humanize_timedelta(dt)`: Returns human-readable strings like "5 minutes ago" or "tomorrow".
|
|
283
265
|
|
|
284
|
-
|
|
266
|
+
### Example of @retry usage:
|
|
285
267
|
|
|
286
268
|
```python
|
|
287
269
|
from chutils.decorators import retry
|
|
@@ -293,7 +275,66 @@ def fetch_data():
|
|
|
293
275
|
...
|
|
294
276
|
```
|
|
295
277
|
|
|
278
|
+
## Command Line Interface (CLI)
|
|
279
|
+
|
|
280
|
+
`chutils` includes a set of tools to speed up development and debugging.
|
|
281
|
+
|
|
282
|
+
### 1. Initialize Project
|
|
283
|
+
|
|
284
|
+
Quickly set up a new project with a default configuration and `.gitignore` rules:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Interactive mode
|
|
288
|
+
chutils init
|
|
289
|
+
|
|
290
|
+
# Non-interactive mode (default values)
|
|
291
|
+
chutils init -y
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### 2. Validate Configuration
|
|
295
|
+
|
|
296
|
+
Check if your configuration files match your Pydantic models:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Automatically finds 'Settings' class in context.py or config.py
|
|
300
|
+
chutils validate
|
|
301
|
+
|
|
302
|
+
# Explicitly specify the model path
|
|
303
|
+
chutils validate --model src.settings:AppConfig
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### 3. Debug Search Paths
|
|
307
|
+
|
|
308
|
+
See exactly where `chutils` is looking for configuration files:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Human-readable output
|
|
312
|
+
chutils show-paths
|
|
313
|
+
|
|
314
|
+
# JSON output for automation
|
|
315
|
+
chutils show-paths --json
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### 4. Manage Secrets
|
|
319
|
+
|
|
320
|
+
Manage your system keyring secrets directly from the terminal:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Set a secret
|
|
324
|
+
chutils secrets set API_KEY "your-secret-value" --service my_app
|
|
325
|
+
|
|
326
|
+
# Delete a secret
|
|
327
|
+
chutils secrets delete API_KEY --service my_app
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### 5. Debug Configuration
|
|
331
|
+
|
|
332
|
+
Trace exactly where each configuration value comes from:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
chutils config debug
|
|
336
|
+
```
|
|
337
|
+
|
|
296
338
|
## License
|
|
297
339
|
|
|
298
340
|
The project is distributed under the MIT License.
|
|
299
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "chutils"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.7.1"
|
|
4
4
|
description = "Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах."
|
|
5
5
|
authors = [{name = "Chu4hel", email = "sergeiivanov636@gmail.com"}]
|
|
6
6
|
license = "MIT"
|
|
@@ -14,13 +14,33 @@ dependencies = [
|
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
[project.optional-dependencies]
|
|
17
|
+
secrets = ["keyring (>=25.7.0)"]
|
|
17
18
|
pydantic = ["pydantic (>=2.13.4,<3.0.0)"]
|
|
18
19
|
json = ["python-json-logger (>=3.2.1)"]
|
|
19
20
|
watch = ["watchdog (>=6.0.0)"]
|
|
21
|
+
rich = ["rich (>=15.0.0)"]
|
|
22
|
+
date = ["python-dateutil (>=2.9.0)"]
|
|
23
|
+
testing = [
|
|
24
|
+
"pytest (>=8.0.0) ; python_full_version < '3.10'",
|
|
25
|
+
"pytest (>=9.0.3) ; python_full_version >= '3.10'"
|
|
26
|
+
]
|
|
27
|
+
otel = [
|
|
28
|
+
"opentelemetry-api (>=1.41.1)",
|
|
29
|
+
"opentelemetry-sdk (>=1.41.1)",
|
|
30
|
+
"opentelemetry-exporter-otlp (>=1.41.1)"
|
|
31
|
+
]
|
|
20
32
|
full = [
|
|
21
33
|
"pydantic (>=2.13.4)",
|
|
22
34
|
"python-json-logger (>=3.2.1)",
|
|
23
|
-
"watchdog (>=6.0.0)"
|
|
35
|
+
"watchdog (>=6.0.0)",
|
|
36
|
+
"rich (>=15.0.0)",
|
|
37
|
+
"python-dateutil (>=2.9.0)",
|
|
38
|
+
"opentelemetry-api (>=1.41.1)",
|
|
39
|
+
"opentelemetry-sdk (>=1.41.1)",
|
|
40
|
+
"opentelemetry-exporter-otlp (>=1.41.1)",
|
|
41
|
+
"keyring (>=25.7.0)",
|
|
42
|
+
"pytest (>=8.0.0) ; python_full_version < '3.10'",
|
|
43
|
+
"pytest (>=9.0.3) ; python_full_version >= '3.10'"
|
|
24
44
|
]
|
|
25
45
|
|
|
26
46
|
[project.scripts]
|
|
@@ -59,6 +79,7 @@ mkdocstrings-python = { version = "^2.0.3", python = ">=3.10" }
|
|
|
59
79
|
pytest-cov = "^7.1.0"
|
|
60
80
|
pytest-asyncio = { version = "^1.3.0", python = ">=3.10" }
|
|
61
81
|
ruff = "^0.15.12"
|
|
82
|
+
rich = "^15.0.0"
|
|
62
83
|
|
|
63
84
|
[build-system]
|
|
64
85
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Пакет chutils - набор переиспользуемых утилит для Python.
|
|
3
|
+
|
|
4
|
+
Основная цель - упростить рутинные задачи, такие как работа с конфигурацией,
|
|
5
|
+
логированием и управлением секретами, с минимальными усилиями со стороны разработчика.
|
|
6
|
+
|
|
7
|
+
Ключевые особенности:
|
|
8
|
+
- Автоматическое обнаружение корня проекта и файла конфигурации.
|
|
9
|
+
- Поддержка форматов `config.yml`, `config.yaml` и `config.ini` (YAML в приоритете).
|
|
10
|
+
- Удобные функции для доступа к настройкам, включая разрешение путей.
|
|
11
|
+
- Асинхронные версии основных функций для неблокирующей работы.
|
|
12
|
+
- Готовый к работе логгер с выводом в консоль и ротируемые файлы.
|
|
13
|
+
- Безопасное хранение секретов через системное хранилище (keyring).
|
|
14
|
+
|
|
15
|
+
Основное использование:
|
|
16
|
+
----------------------
|
|
17
|
+
Вам не нужно ничего инициализировать. Просто импортируйте и используйте:
|
|
18
|
+
|
|
19
|
+
from chutils import get_config_value, setup_logger, SecretManager
|
|
20
|
+
|
|
21
|
+
logger = setup_logger()
|
|
22
|
+
secrets = SecretManager("my_app")
|
|
23
|
+
db_host = get_config_value("Database", "host", "localhost")
|
|
24
|
+
logger.info(f"Подключение к базе данных на {db_host}")
|
|
25
|
+
|
|
26
|
+
Ручная инициализация (для нестандартных случаев):
|
|
27
|
+
-------------------------------------------------
|
|
28
|
+
Если автоматика не сработала, вы можете указать путь к корню проекта вручную:
|
|
29
|
+
|
|
30
|
+
import chutils
|
|
31
|
+
chutils.init(base_dir="/path/to/your/project")
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
import importlib
|
|
36
|
+
import os
|
|
37
|
+
from typing import Any
|
|
38
|
+
|
|
39
|
+
# Словарь соответствия имен атрибутов их модулям и именам внутри этих модулей.
|
|
40
|
+
# Формат: 'имя_атрибута': ('относительный_путь_к_модулю', 'имя_в_модуле' или None для самого модуля)
|
|
41
|
+
_LAZY_MAPPING = {
|
|
42
|
+
# modules
|
|
43
|
+
'config': ('.config', None),
|
|
44
|
+
'logger': ('.logger', None),
|
|
45
|
+
'secret_manager': ('.secret_manager', None),
|
|
46
|
+
'decorators': ('.decorators', None),
|
|
47
|
+
'cache': ('.cache', None),
|
|
48
|
+
'exceptions': ('.exceptions', None),
|
|
49
|
+
'context': ('.context', None),
|
|
50
|
+
'lifecycle': ('.lifecycle', None),
|
|
51
|
+
'time': ('.time', None),
|
|
52
|
+
'tracing': ('.tracing', None),
|
|
53
|
+
'testing': ('.testing', None),
|
|
54
|
+
|
|
55
|
+
# config
|
|
56
|
+
'get_config': ('.config', 'get_config'),
|
|
57
|
+
'get_config_value': ('.config', 'get_config_value'),
|
|
58
|
+
'get_config_int': ('.config', 'get_config_int'),
|
|
59
|
+
'get_config_float': ('.config', 'get_config_float'),
|
|
60
|
+
'get_config_boolean': ('.config', 'get_config_boolean'),
|
|
61
|
+
'get_config_list': ('.config', 'get_config_list'),
|
|
62
|
+
'get_config_section': ('.config', 'get_config_section'),
|
|
63
|
+
'get_config_path': ('.config', 'get_config_path'),
|
|
64
|
+
'aget_config': ('.config', 'aget_config'),
|
|
65
|
+
'save_config_value': ('.config', 'save_config_value'),
|
|
66
|
+
'asave_config_value': ('.config', 'asave_config_value'),
|
|
67
|
+
'start_config_watcher': ('.config', 'start_config_watcher'),
|
|
68
|
+
'stop_config_watcher': ('.config', 'stop_config_watcher'),
|
|
69
|
+
'on_config_change': ('.config', 'on_config_change'),
|
|
70
|
+
'generate_yaml_template': ('.config', 'generate_yaml_template'),
|
|
71
|
+
'generate_env_template': ('.config', 'generate_env_template'),
|
|
72
|
+
'generate_json_schema': ('.config', 'generate_json_schema'),
|
|
73
|
+
|
|
74
|
+
# features
|
|
75
|
+
'is_feature_enabled': ('.features', 'is_feature_enabled'),
|
|
76
|
+
'require_feature': ('.features', 'require_feature'),
|
|
77
|
+
|
|
78
|
+
# logger
|
|
79
|
+
'setup_logger': ('.logger', 'setup_logger'),
|
|
80
|
+
'ChutilsLogger': ('.logger', 'ChutilsLogger'),
|
|
81
|
+
'SafeTimedRotatingFileHandler': ('.logger', 'SafeTimedRotatingFileHandler'),
|
|
82
|
+
|
|
83
|
+
# context
|
|
84
|
+
'bind_context': ('.context', 'bind_context'),
|
|
85
|
+
'unbind_context': ('.context', 'unbind_context'),
|
|
86
|
+
'clear_context': ('.context', 'clear_context'),
|
|
87
|
+
|
|
88
|
+
# lifecycle
|
|
89
|
+
'register_cleanup': ('.lifecycle', 'register_cleanup'),
|
|
90
|
+
'setup_graceful_shutdown': ('.lifecycle', 'setup_graceful_shutdown'),
|
|
91
|
+
|
|
92
|
+
# cli_booster
|
|
93
|
+
'cli_command': ('.cli_booster', 'cli_command'),
|
|
94
|
+
|
|
95
|
+
# time
|
|
96
|
+
'utc_now': ('.time', 'utc_now'),
|
|
97
|
+
'parse_datetime': ('.time', 'parse_datetime'),
|
|
98
|
+
'humanize_timedelta': ('.time', 'humanize_timedelta'),
|
|
99
|
+
|
|
100
|
+
# secret_manager
|
|
101
|
+
'SecretManager': ('.secret_manager', 'SecretManager'),
|
|
102
|
+
|
|
103
|
+
# decorators
|
|
104
|
+
'log_function_details': ('.decorators', 'log_function_details'),
|
|
105
|
+
'retry': ('.decorators', 'retry'),
|
|
106
|
+
'timeout': ('.decorators', 'timeout'),
|
|
107
|
+
|
|
108
|
+
# tracing
|
|
109
|
+
'trace': ('.tracing', 'trace'),
|
|
110
|
+
'setup_tracing': ('.tracing', 'setup_tracing'),
|
|
111
|
+
'IS_OTEL_AVAILABLE': ('.tracing', 'IS_OTEL_AVAILABLE'),
|
|
112
|
+
|
|
113
|
+
# exceptions
|
|
114
|
+
'ChutilsException': ('.exceptions', 'ChutilsException'),
|
|
115
|
+
'ConfigError': ('.exceptions', 'ConfigError'),
|
|
116
|
+
'ConfigLoadError': ('.exceptions', 'ConfigLoadError'),
|
|
117
|
+
'ConfigParseError': ('.exceptions', 'ConfigParseError'),
|
|
118
|
+
'SecretError': ('.exceptions', 'SecretError'),
|
|
119
|
+
'SecretNotFoundError': ('.exceptions', 'SecretNotFoundError'),
|
|
120
|
+
'SecretProviderError': ('.exceptions', 'SecretProviderError'),
|
|
121
|
+
'LoggerConfigurationError': ('.exceptions', 'LoggerConfigurationError'),
|
|
122
|
+
'WatcherInitializationError': ('.exceptions', 'WatcherInitializationError'),
|
|
123
|
+
'OptionalDependencyError': ('.exceptions', 'OptionalDependencyError'),
|
|
124
|
+
'ChutilsTimeoutError': ('.exceptions', 'ChutilsTimeoutError'),
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def __getattr__(name: str) -> Any:
|
|
129
|
+
"""
|
|
130
|
+
Реализация ленивой загрузки согласно PEP 562.
|
|
131
|
+
Вызывается при обращении к атрибутам модуля, которые не определены явно.
|
|
132
|
+
"""
|
|
133
|
+
if name in _LAZY_MAPPING:
|
|
134
|
+
mod_path, attr_name = _LAZY_MAPPING[name]
|
|
135
|
+
module = importlib.import_module(mod_path, __name__)
|
|
136
|
+
if attr_name is None:
|
|
137
|
+
return module
|
|
138
|
+
return getattr(module, attr_name)
|
|
139
|
+
|
|
140
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def __dir__():
|
|
144
|
+
"""
|
|
145
|
+
Возвращает список всех доступных атрибутов для поддержки автодополнения и интроспекции.
|
|
146
|
+
"""
|
|
147
|
+
return sorted(list(_LAZY_MAPPING.keys()) + [
|
|
148
|
+
'init', '__all__', '__doc__', '__file__', '__path__',
|
|
149
|
+
'__name__', '__package__', '__spec__'
|
|
150
|
+
])
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def init(base_dir: str):
|
|
154
|
+
"""
|
|
155
|
+
Ручная инициализация пакета с указанием базовой директории проекта.
|
|
156
|
+
|
|
157
|
+
Эту функцию нужно вызывать только в том случае, если автоматическое
|
|
158
|
+
определение корня проекта не сработало. Вызывать следует один раз
|
|
159
|
+
в самом начале работы основного скрипта вашего приложения.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
base_dir (str): Абсолютный путь к корневой директории проекта.
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
ChutilsException: Если указанная директория не существует.
|
|
166
|
+
"""
|
|
167
|
+
if not os.path.isdir(base_dir):
|
|
168
|
+
# Импортируем исключение лениво
|
|
169
|
+
from .exceptions import ChutilsException
|
|
170
|
+
raise ChutilsException(
|
|
171
|
+
f"Указанная директория base_dir не существует или не является директорией: {base_dir}",
|
|
172
|
+
base_dir=base_dir
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Вручную устанавливаем базовую директорию через менеджер состояний.
|
|
176
|
+
from .config.manager import _cm
|
|
177
|
+
_cm.base_dir = base_dir
|
|
178
|
+
_cm.paths_initialized = True
|
|
179
|
+
|
|
180
|
+
print(f"Пакет chutils вручную инициализирован с базовой директорией: {base_dir}")
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
# --- Определение публичного API (`__all__`) ---
|
|
184
|
+
__all__ = list(_LAZY_MAPPING.keys()) + ['init']
|