chutils 2.6.0__tar.gz → 2.6.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.0 → chutils-2.6.1}/PKG-INFO +1 -1
- {chutils-2.6.0 → chutils-2.6.1}/pyproject.toml +1 -1
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/config/__init__.py +60 -15
- {chutils-2.6.0 → chutils-2.6.1}/LICENSE +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/README.md +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/__init__.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/cli.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/config/manager.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/config/providers.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/config/utils.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/config/watcher.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/context.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/decorators.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/logger.py +0 -0
- {chutils-2.6.0 → chutils-2.6.1}/src/chutils/secret_manager.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "chutils"
|
|
3
|
-
version = "2.6.
|
|
3
|
+
version = "2.6.1"
|
|
4
4
|
description = "Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах."
|
|
5
5
|
authors = [{name = "Chu4hel", email = "sergeiivanov636@gmail.com"}]
|
|
6
6
|
license = "MIT"
|
|
@@ -23,7 +23,7 @@ import os
|
|
|
23
23
|
import time
|
|
24
24
|
import warnings
|
|
25
25
|
from pathlib import Path
|
|
26
|
-
from typing import Any, Optional, List, Dict, TYPE_CHECKING, TypeVar, Type, overload, Union
|
|
26
|
+
from typing import Any, Optional, List, Dict, TYPE_CHECKING, TypeVar, Type, overload, Union, Tuple
|
|
27
27
|
|
|
28
28
|
from .manager import _cm
|
|
29
29
|
from .providers import get_providers
|
|
@@ -69,25 +69,30 @@ def __getattr__(name: str) -> Any:
|
|
|
69
69
|
в новый менеджер состояния с выводом предупреждения об устаревании.
|
|
70
70
|
"""
|
|
71
71
|
remap = {
|
|
72
|
-
'_BASE_DIR': 'base_dir',
|
|
73
|
-
'_CONFIG_FILE_PATH': 'config_file_path',
|
|
74
|
-
'_paths_initialized': 'paths_initialized',
|
|
75
|
-
'_config_object': 'config_object',
|
|
76
|
-
'_config_loaded': 'config_loaded'
|
|
72
|
+
'_BASE_DIR': ('base_dir', 'get_base_dir()'),
|
|
73
|
+
'_CONFIG_FILE_PATH': ('config_file_path', 'get_config_file_path()'),
|
|
74
|
+
'_paths_initialized': ('paths_initialized', 'are_paths_initialized()'),
|
|
75
|
+
'_config_object': ('config_object', 'get_config()'),
|
|
76
|
+
'_config_loaded': ('config_loaded', 'is_config_loaded()'),
|
|
77
|
+
'_get_config_paths': ('get_config_paths', 'get_config_paths()')
|
|
77
78
|
}
|
|
79
|
+
"Словарь соответствия: имя -> (атрибут в _cm, рекомендуемая публичная замена)"
|
|
78
80
|
|
|
79
81
|
if name in remap:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
cm_attr, suggestion = remap[name]
|
|
83
|
+
msg = f"Прямое обращение к 'chutils.config.{name}' устарело и будет удалено в будущих версиях."
|
|
84
|
+
if suggestion:
|
|
85
|
+
msg += f" Используйте {suggestion}."
|
|
86
|
+
else:
|
|
87
|
+
msg += " Используйте публичный API модуля."
|
|
88
|
+
|
|
89
|
+
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
90
|
+
|
|
86
91
|
# Если пути еще не инициализированы, инициализируем их при первом обращении
|
|
87
|
-
if name in ['_BASE_DIR', '_CONFIG_FILE_PATH'] and not _cm.paths_initialized:
|
|
92
|
+
if name in ['_BASE_DIR', '_CONFIG_FILE_PATH', '_get_config_paths'] and not _cm.paths_initialized:
|
|
88
93
|
_cm.initialize_paths(find_project_root)
|
|
89
94
|
|
|
90
|
-
return getattr(_cm,
|
|
95
|
+
return getattr(_cm, cm_attr)
|
|
91
96
|
|
|
92
97
|
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
93
98
|
|
|
@@ -158,6 +163,31 @@ def is_config_loaded() -> bool:
|
|
|
158
163
|
return _cm.config_loaded
|
|
159
164
|
|
|
160
165
|
|
|
166
|
+
def are_paths_initialized() -> bool:
|
|
167
|
+
"""
|
|
168
|
+
Проверяет, были ли инициализированы пути к проекту и файлам конфигурации.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
True, если пути определены.
|
|
172
|
+
"""
|
|
173
|
+
return _cm.paths_initialized
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def get_config_paths(cfg_file: Optional[str] = None) -> Tuple[Optional[str], Optional[str]]:
|
|
177
|
+
"""
|
|
178
|
+
Возвращает пути к основному и локальному файлам конфигурации.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
cfg_file: Опциональный путь к основному файлу.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Кортеж (путь_к_основному, путь_к_локальному).
|
|
185
|
+
"""
|
|
186
|
+
if not _cm.paths_initialized:
|
|
187
|
+
_cm.initialize_paths(find_project_root)
|
|
188
|
+
return _cm.get_config_paths(cfg_file)
|
|
189
|
+
|
|
190
|
+
|
|
161
191
|
def _check_pydantic():
|
|
162
192
|
"""Проверяет наличие установленного пакета pydantic."""
|
|
163
193
|
try:
|
|
@@ -597,6 +627,21 @@ def get_config_path(
|
|
|
597
627
|
|
|
598
628
|
# Если путь относительный, _BASE_DIR определен и resolve_from_root включен, объединяем их
|
|
599
629
|
if resolve_from_root and not path_obj.is_absolute() and base_dir:
|
|
600
|
-
|
|
630
|
+
# Безопасное разрешение пути с проверкой на выход за пределы корня проекта (Path Traversal)
|
|
631
|
+
try:
|
|
632
|
+
base_dir_obj = Path(base_dir).resolve()
|
|
633
|
+
resolved_path = (base_dir_obj / path_obj).resolve()
|
|
634
|
+
|
|
635
|
+
# Проверяем, что итоговый путь находится внутри базовой директории
|
|
636
|
+
if not str(resolved_path).startswith(str(base_dir_obj)):
|
|
637
|
+
_get_logger().warning(
|
|
638
|
+
"Обнаружена попытка выхода за пределы корня проекта (Path Traversal). "
|
|
639
|
+
"Путь '%s' отклонен. Возвращено значение по умолчанию.", path_str
|
|
640
|
+
)
|
|
641
|
+
return fallback
|
|
642
|
+
return str(resolved_path)
|
|
643
|
+
except Exception as e:
|
|
644
|
+
_get_logger().error("Ошибка при разрешении пути '%s': %s", path_str, e)
|
|
645
|
+
return fallback
|
|
601
646
|
|
|
602
647
|
return path_str
|
|
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
|