fishertools 0.2.1__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.
Files changed (81) hide show
  1. fishertools/__init__.py +82 -0
  2. fishertools/config/__init__.py +24 -0
  3. fishertools/config/manager.py +247 -0
  4. fishertools/config/models.py +96 -0
  5. fishertools/config/parser.py +265 -0
  6. fishertools/decorators.py +93 -0
  7. fishertools/documentation/__init__.py +38 -0
  8. fishertools/documentation/api.py +242 -0
  9. fishertools/documentation/generator.py +502 -0
  10. fishertools/documentation/models.py +126 -0
  11. fishertools/documentation/visual.py +583 -0
  12. fishertools/errors/__init__.py +29 -0
  13. fishertools/errors/exceptions.py +191 -0
  14. fishertools/errors/explainer.py +303 -0
  15. fishertools/errors/formatters.py +386 -0
  16. fishertools/errors/models.py +228 -0
  17. fishertools/errors/patterns.py +119 -0
  18. fishertools/errors/recovery.py +467 -0
  19. fishertools/examples/__init__.py +22 -0
  20. fishertools/examples/models.py +118 -0
  21. fishertools/examples/repository.py +770 -0
  22. fishertools/helpers.py +116 -0
  23. fishertools/integration.py +451 -0
  24. fishertools/learn/__init__.py +18 -0
  25. fishertools/learn/examples.py +550 -0
  26. fishertools/learn/tips.py +281 -0
  27. fishertools/learning/__init__.py +32 -0
  28. fishertools/learning/core.py +349 -0
  29. fishertools/learning/models.py +112 -0
  30. fishertools/learning/progress.py +314 -0
  31. fishertools/learning/session.py +500 -0
  32. fishertools/learning/tutorial.py +626 -0
  33. fishertools/legacy/__init__.py +76 -0
  34. fishertools/legacy/deprecated.py +261 -0
  35. fishertools/legacy/deprecation.py +149 -0
  36. fishertools/safe/__init__.py +16 -0
  37. fishertools/safe/collections.py +242 -0
  38. fishertools/safe/files.py +240 -0
  39. fishertools/safe/strings.py +15 -0
  40. fishertools/utils.py +57 -0
  41. fishertools-0.2.1.dist-info/METADATA +256 -0
  42. fishertools-0.2.1.dist-info/RECORD +81 -0
  43. fishertools-0.2.1.dist-info/WHEEL +5 -0
  44. fishertools-0.2.1.dist-info/licenses/LICENSE +21 -0
  45. fishertools-0.2.1.dist-info/top_level.txt +2 -0
  46. tests/__init__.py +6 -0
  47. tests/conftest.py +25 -0
  48. tests/test_config/__init__.py +3 -0
  49. tests/test_config/test_basic_config.py +57 -0
  50. tests/test_config/test_config_error_handling.py +287 -0
  51. tests/test_config/test_config_properties.py +435 -0
  52. tests/test_documentation/__init__.py +3 -0
  53. tests/test_documentation/test_documentation_properties.py +253 -0
  54. tests/test_documentation/test_visual_documentation_properties.py +444 -0
  55. tests/test_errors/__init__.py +3 -0
  56. tests/test_errors/test_api.py +301 -0
  57. tests/test_errors/test_error_handling.py +354 -0
  58. tests/test_errors/test_explainer.py +173 -0
  59. tests/test_errors/test_formatters.py +338 -0
  60. tests/test_errors/test_models.py +248 -0
  61. tests/test_errors/test_patterns.py +270 -0
  62. tests/test_examples/__init__.py +3 -0
  63. tests/test_examples/test_example_repository_properties.py +204 -0
  64. tests/test_examples/test_specific_examples.py +303 -0
  65. tests/test_integration.py +298 -0
  66. tests/test_integration_enhancements.py +462 -0
  67. tests/test_learn/__init__.py +3 -0
  68. tests/test_learn/test_examples.py +221 -0
  69. tests/test_learn/test_tips.py +285 -0
  70. tests/test_learning/__init__.py +3 -0
  71. tests/test_learning/test_interactive_learning_properties.py +337 -0
  72. tests/test_learning/test_learning_system_properties.py +194 -0
  73. tests/test_learning/test_progress_tracking_properties.py +279 -0
  74. tests/test_legacy/__init__.py +3 -0
  75. tests/test_legacy/test_backward_compatibility.py +236 -0
  76. tests/test_legacy/test_deprecation_warnings.py +208 -0
  77. tests/test_safe/__init__.py +3 -0
  78. tests/test_safe/test_collections_properties.py +189 -0
  79. tests/test_safe/test_files.py +104 -0
  80. tests/test_structure.py +58 -0
  81. tests/test_structure_enhancements.py +115 -0
@@ -0,0 +1,76 @@
1
+ """
2
+ Legacy module for backward compatibility
3
+
4
+ This module contains functions from the original fishertools library that align
5
+ with the new mission of making Python more convenient and safer for beginners.
6
+ All functions maintain identical behavior for backward compatibility.
7
+
8
+ It also includes deprecated functions with clear migration guidance.
9
+ """
10
+
11
+ # Import deprecation system
12
+ from .deprecation import (
13
+ deprecated,
14
+ show_deprecation_info,
15
+ list_deprecated_functions,
16
+ # Example deprecated functions for demonstration
17
+ unsafe_file_reader,
18
+ risky_divide,
19
+ complex_list_operation,
20
+ )
21
+
22
+ # Import retained functions that align with beginner-friendly mission
23
+ from .deprecated import (
24
+ # File and directory utilities - helpful for beginners
25
+ read_json,
26
+ write_json,
27
+ ensure_dir,
28
+ get_file_size,
29
+ list_files,
30
+
31
+ # String utilities - common beginner needs
32
+ clean_string,
33
+ validate_email,
34
+
35
+ # Data utilities - safe operations for beginners
36
+ chunk_list,
37
+ merge_dicts,
38
+ flatten_dict,
39
+
40
+ # Configuration helper - simplified config management
41
+ QuickConfig,
42
+
43
+ # Simple logging - educational and beginner-friendly
44
+ SimpleLogger,
45
+
46
+ # Decorators that help beginners understand code behavior
47
+ timer,
48
+ debug,
49
+ retry,
50
+ cache_result,
51
+ validate_types,
52
+
53
+ # Utility functions
54
+ timestamp,
55
+ generate_password,
56
+ hash_string,
57
+ )
58
+
59
+ __all__ = [
60
+ # Deprecation system
61
+ 'deprecated', 'show_deprecation_info', 'list_deprecated_functions',
62
+ # Example deprecated functions
63
+ 'unsafe_file_reader', 'risky_divide', 'complex_list_operation',
64
+ # File operations
65
+ 'read_json', 'write_json', 'ensure_dir', 'get_file_size', 'list_files',
66
+ # String operations
67
+ 'clean_string', 'validate_email',
68
+ # Data operations
69
+ 'chunk_list', 'merge_dicts', 'flatten_dict',
70
+ # Helper classes
71
+ 'QuickConfig', 'SimpleLogger',
72
+ # Decorators
73
+ 'timer', 'debug', 'retry', 'cache_result', 'validate_types',
74
+ # Utilities
75
+ 'timestamp', 'generate_password', 'hash_string',
76
+ ]
@@ -0,0 +1,261 @@
1
+ """
2
+ Deprecated functions from original fishertools library
3
+
4
+ These functions are retained for backward compatibility and align with the new
5
+ mission of making Python more convenient and safer for beginners. All functions
6
+ maintain identical behavior to the original implementation.
7
+ """
8
+
9
+ import json
10
+ import os
11
+ import time
12
+ import re
13
+ import hashlib
14
+ import random
15
+ import string
16
+ import functools
17
+ from pathlib import Path
18
+ from typing import Any, Dict, List, Optional, Callable
19
+
20
+
21
+ # File and directory utilities - helpful for beginners
22
+ def read_json(filepath: str) -> Dict[str, Any]:
23
+ """Читает JSON файл и возвращает словарь"""
24
+ with open(filepath, 'r', encoding='utf-8') as f:
25
+ return json.load(f)
26
+
27
+
28
+ def write_json(data: Dict[str, Any], filepath: str, indent: int = 2) -> None:
29
+ """Записывает данные в JSON файл"""
30
+ with open(filepath, 'w', encoding='utf-8') as f:
31
+ json.dump(data, f, ensure_ascii=False, indent=indent)
32
+
33
+
34
+ def ensure_dir(path: str) -> None:
35
+ """Создает директорию если она не существует"""
36
+ Path(path).mkdir(parents=True, exist_ok=True)
37
+
38
+
39
+ def get_file_size(filepath: str) -> int:
40
+ """Возвращает размер файла в байтах"""
41
+ return os.path.getsize(filepath)
42
+
43
+
44
+ def list_files(directory: str, extension: Optional[str] = None) -> List[str]:
45
+ """Возвращает список файлов в директории с опциональной фильтрацией по расширению"""
46
+ path = Path(directory)
47
+ if extension:
48
+ pattern = f"*.{extension.lstrip('.')}"
49
+ return [str(f) for f in path.glob(pattern)]
50
+ return [str(f) for f in path.iterdir() if f.is_file()]
51
+
52
+
53
+ def timestamp() -> str:
54
+ """Возвращает текущую временную метку в читаемом формате"""
55
+ return time.strftime("%Y-%m-%d %H:%M:%S")
56
+
57
+
58
+ def flatten_dict(d: Dict[str, Any], parent_key: str = '', sep: str = '.') -> Dict[str, Any]:
59
+ """Превращает вложенный словарь в плоский"""
60
+ items = []
61
+ for k, v in d.items():
62
+ new_key = f"{parent_key}{sep}{k}" if parent_key else k
63
+ if isinstance(v, dict):
64
+ items.extend(flatten_dict(v, new_key, sep=sep).items())
65
+ else:
66
+ items.append((new_key, v))
67
+ return dict(items)
68
+
69
+
70
+ # String utilities - common beginner needs
71
+ def validate_email(email: str) -> bool:
72
+ """Проверяет корректность email адреса"""
73
+ pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
74
+ return bool(re.match(pattern, email))
75
+
76
+
77
+ def clean_string(text: str) -> str:
78
+ """Очищает строку от лишних пробелов и символов"""
79
+ # Убираем лишние пробелы
80
+ text = re.sub(r'\s+', ' ', text.strip())
81
+ # Убираем специальные символы (оставляем только буквы, цифры, пробелы и основную пунктуацию)
82
+ text = re.sub(r'[^\w\s.,!?-]', '', text)
83
+ return text
84
+
85
+
86
+ # Data utilities - safe operations for beginners
87
+ def chunk_list(lst: List[Any], chunk_size: int) -> List[List[Any]]:
88
+ """Разбивает список на части заданного размера"""
89
+ return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]
90
+
91
+
92
+ def merge_dicts(*dicts: Dict[str, Any]) -> Dict[str, Any]:
93
+ """Объединяет несколько словарей в один"""
94
+ result = {}
95
+ for d in dicts:
96
+ result.update(d)
97
+ return result
98
+
99
+
100
+ # Security utilities - helpful for beginners
101
+ def generate_password(length: int = 12, include_symbols: bool = True) -> str:
102
+ """Генерирует случайный пароль"""
103
+ chars = string.ascii_letters + string.digits
104
+ if include_symbols:
105
+ chars += "!@#$%^&*"
106
+
107
+ return ''.join(random.choice(chars) for _ in range(length))
108
+
109
+
110
+ def hash_string(text: str, algorithm: str = 'sha256') -> str:
111
+ """Хеширует строку указанным алгоритмом"""
112
+ hash_obj = hashlib.new(algorithm)
113
+ hash_obj.update(text.encode('utf-8'))
114
+ return hash_obj.hexdigest()
115
+
116
+
117
+ # Helper classes - simplified for beginners
118
+ class QuickConfig:
119
+ """Простой класс для работы с конфигурацией"""
120
+
121
+ def __init__(self, config_dict: Optional[Dict[str, Any]] = None):
122
+ self._config = config_dict or {}
123
+
124
+ def get(self, key: str, default: Any = None) -> Any:
125
+ """Получить значение по ключу с поддержкой точечной нотации"""
126
+ keys = key.split('.')
127
+ value = self._config
128
+
129
+ for k in keys:
130
+ if isinstance(value, dict) and k in value:
131
+ value = value[k]
132
+ else:
133
+ return default
134
+
135
+ return value
136
+
137
+ def set(self, key: str, value: Any) -> None:
138
+ """Установить значение по ключу с поддержкой точечной нотации"""
139
+ keys = key.split('.')
140
+ config = self._config
141
+
142
+ for k in keys[:-1]:
143
+ if k not in config:
144
+ config[k] = {}
145
+ config = config[k]
146
+
147
+ config[keys[-1]] = value
148
+
149
+ def to_dict(self) -> Dict[str, Any]:
150
+ """Вернуть конфигурацию как словарь"""
151
+ return self._config.copy()
152
+
153
+
154
+ class SimpleLogger:
155
+ """Простой логгер для быстрой отладки"""
156
+
157
+ def __init__(self, name: str = "MyDevTools"):
158
+ self.name = name
159
+
160
+ def info(self, message: str) -> None:
161
+ """Информационное сообщение"""
162
+ print(f"[{self.name}] INFO: {message}")
163
+
164
+ def warning(self, message: str) -> None:
165
+ """Предупреждение"""
166
+ print(f"[{self.name}] WARNING: {message}")
167
+
168
+ def error(self, message: str) -> None:
169
+ """Ошибка"""
170
+ print(f"[{self.name}] ERROR: {message}")
171
+
172
+ def debug(self, message: str) -> None:
173
+ """Отладочное сообщение"""
174
+ print(f"[{self.name}] DEBUG: {message}")
175
+
176
+
177
+ # Educational decorators - help beginners understand code behavior
178
+ def timer(func: Callable) -> Callable:
179
+ """Декоратор для измерения времени выполнения функции"""
180
+ @functools.wraps(func)
181
+ def wrapper(*args, **kwargs):
182
+ start_time = time.time()
183
+ result = func(*args, **kwargs)
184
+ end_time = time.time()
185
+ print(f"{func.__name__} выполнилась за {end_time - start_time:.4f} секунд")
186
+ return result
187
+ return wrapper
188
+
189
+
190
+ def debug(func: Callable) -> Callable:
191
+ """Декоратор для отладки - выводит аргументы и результат функции"""
192
+ @functools.wraps(func)
193
+ def wrapper(*args, **kwargs):
194
+ print(f"Вызов {func.__name__} с аргументами: args={args}, kwargs={kwargs}")
195
+ result = func(*args, **kwargs)
196
+ print(f"{func.__name__} вернула: {result}")
197
+ return result
198
+ return wrapper
199
+
200
+
201
+ def retry(max_attempts: int = 3, delay: float = 1.0):
202
+ """Декоратор для повторных попыток выполнения функции при ошибке"""
203
+ def decorator(func: Callable) -> Callable:
204
+ @functools.wraps(func)
205
+ def wrapper(*args, **kwargs):
206
+ for attempt in range(max_attempts):
207
+ try:
208
+ return func(*args, **kwargs)
209
+ except Exception as e:
210
+ if attempt == max_attempts - 1:
211
+ raise e
212
+ print(f"Попытка {attempt + 1} не удалась: {e}. Повтор через {delay} сек...")
213
+ time.sleep(delay)
214
+ return wrapper
215
+ return decorator
216
+
217
+
218
+ def cache_result(func: Callable) -> Callable:
219
+ """Простой декоратор для кеширования результатов функции"""
220
+ cache = {}
221
+
222
+ @functools.wraps(func)
223
+ def wrapper(*args, **kwargs):
224
+ # Создаем ключ из аргументов
225
+ key = str(args) + str(sorted(kwargs.items()))
226
+
227
+ if key in cache:
228
+ print(f"Результат {func.__name__} взят из кеша")
229
+ return cache[key]
230
+
231
+ result = func(*args, **kwargs)
232
+ cache[key] = result
233
+ return result
234
+
235
+ return wrapper
236
+
237
+
238
+ def validate_types(**expected_types):
239
+ """Декоратор для проверки типов аргументов функции"""
240
+ def decorator(func: Callable) -> Callable:
241
+ @functools.wraps(func)
242
+ def wrapper(*args, **kwargs):
243
+ # Получаем имена параметров функции
244
+ import inspect
245
+ sig = inspect.signature(func)
246
+ bound_args = sig.bind(*args, **kwargs)
247
+ bound_args.apply_defaults()
248
+
249
+ # Проверяем типы
250
+ for param_name, expected_type in expected_types.items():
251
+ if param_name in bound_args.arguments:
252
+ value = bound_args.arguments[param_name]
253
+ if not isinstance(value, expected_type):
254
+ raise TypeError(
255
+ f"Параметр '{param_name}' должен быть типа {expected_type.__name__}, "
256
+ f"получен {type(value).__name__}"
257
+ )
258
+
259
+ return func(*args, **kwargs)
260
+ return wrapper
261
+ return decorator
@@ -0,0 +1,149 @@
1
+ """
2
+ Deprecation warning system for fishertools
3
+
4
+ This module provides utilities for managing deprecation warnings and
5
+ migration guidance for functions being removed from the library.
6
+ """
7
+
8
+ import warnings
9
+ import functools
10
+ from typing import Callable, Optional
11
+
12
+
13
+ def deprecated(
14
+ reason: str = "This function is deprecated",
15
+ alternative: Optional[str] = None,
16
+ removal_version: Optional[str] = None
17
+ ) -> Callable:
18
+ """
19
+ Decorator to mark functions as deprecated with clear migration guidance.
20
+
21
+ Args:
22
+ reason: Explanation of why the function is deprecated
23
+ alternative: Suggested replacement function or approach
24
+ removal_version: Version when the function will be removed
25
+
26
+ Returns:
27
+ Decorated function that issues deprecation warning when called
28
+ """
29
+ def decorator(func: Callable) -> Callable:
30
+ @functools.wraps(func)
31
+ def wrapper(*args, **kwargs):
32
+ # Build comprehensive warning message
33
+ message_parts = [
34
+ f"Функция '{func.__name__}' устарела.",
35
+ reason
36
+ ]
37
+
38
+ if alternative:
39
+ message_parts.append(f"Используйте вместо неё: {alternative}")
40
+
41
+ if removal_version:
42
+ message_parts.append(f"Будет удалена в версии {removal_version}")
43
+
44
+ message_parts.append("Подробности миграции: https://github.com/f1sherFM/fishertools/wiki/migration")
45
+
46
+ warning_message = " ".join(message_parts)
47
+
48
+ # Issue deprecation warning
49
+ warnings.warn(
50
+ warning_message,
51
+ DeprecationWarning,
52
+ stacklevel=2
53
+ )
54
+
55
+ # Execute original function
56
+ return func(*args, **kwargs)
57
+
58
+ # Mark function as deprecated for introspection
59
+ wrapper._is_deprecated = True
60
+ wrapper._deprecation_info = {
61
+ 'reason': reason,
62
+ 'alternative': alternative,
63
+ 'removal_version': removal_version
64
+ }
65
+
66
+ return wrapper
67
+ return decorator
68
+
69
+
70
+ def show_deprecation_info(func: Callable) -> dict:
71
+ """
72
+ Get deprecation information for a function.
73
+
74
+ Args:
75
+ func: Function to check for deprecation info
76
+
77
+ Returns:
78
+ Dictionary with deprecation details or empty dict if not deprecated
79
+ """
80
+ if hasattr(func, '_is_deprecated') and func._is_deprecated:
81
+ return func._deprecation_info.copy()
82
+ return {}
83
+
84
+
85
+ def list_deprecated_functions(module) -> list:
86
+ """
87
+ List all deprecated functions in a module.
88
+
89
+ Args:
90
+ module: Module to scan for deprecated functions
91
+
92
+ Returns:
93
+ List of deprecated function names
94
+ """
95
+ deprecated_funcs = []
96
+
97
+ for name in dir(module):
98
+ obj = getattr(module, name)
99
+ if callable(obj) and hasattr(obj, '_is_deprecated') and obj._is_deprecated:
100
+ deprecated_funcs.append(name)
101
+
102
+ return deprecated_funcs
103
+
104
+
105
+ # Example deprecated functions for demonstration
106
+ @deprecated(
107
+ reason="Эта функция не соответствует новой миссии библиотеки",
108
+ alternative="fishertools.safe.safe_read_file()",
109
+ removal_version="1.0.0"
110
+ )
111
+ def unsafe_file_reader(filepath: str) -> str:
112
+ """
113
+ DEPRECATED: Небезопасное чтение файла без обработки ошибок
114
+
115
+ Эта функция устарела и будет удалена в версии 1.0.0.
116
+ Используйте вместо неё fishertools.safe.safe_read_file()
117
+ """
118
+ with open(filepath, 'r') as f:
119
+ return f.read()
120
+
121
+
122
+ @deprecated(
123
+ reason="Функция может вызывать ошибки у новичков",
124
+ alternative="fishertools.safe.safe_divide()",
125
+ removal_version="1.0.0"
126
+ )
127
+ def risky_divide(a: float, b: float) -> float:
128
+ """
129
+ DEPRECATED: Деление без проверки на ноль
130
+
131
+ Эта функция устарела и будет удалена в версии 1.0.0.
132
+ Используйте вместо неё fishertools.safe.safe_divide()
133
+ """
134
+ return a / b
135
+
136
+
137
+ @deprecated(
138
+ reason="Слишком сложная для новичков",
139
+ alternative="Используйте стандартные методы списков",
140
+ removal_version="1.0.0"
141
+ )
142
+ def complex_list_operation(lst: list) -> list:
143
+ """
144
+ DEPRECATED: Сложная операция со списком
145
+
146
+ Эта функция устарела и будет удалена в версии 1.0.0.
147
+ Используйте стандартные методы списков для простоты.
148
+ """
149
+ return [x for i, x in enumerate(lst) if i % 2 == 0 and x is not None]
@@ -0,0 +1,16 @@
1
+ """
2
+ Safe utilities module for fishertools.
3
+
4
+ This module provides beginner-friendly versions of common operations
5
+ that prevent typical mistakes and provide helpful error messages.
6
+ """
7
+
8
+ from .collections import safe_get, safe_divide, safe_max, safe_min, safe_sum
9
+ from .files import safe_read_file, safe_write_file, safe_file_exists, safe_get_file_size, safe_list_files
10
+ from .strings import safe_string_operations
11
+
12
+ __all__ = [
13
+ "safe_get", "safe_divide", "safe_max", "safe_min", "safe_sum",
14
+ "safe_read_file", "safe_write_file", "safe_file_exists", "safe_get_file_size", "safe_list_files",
15
+ "safe_string_operations"
16
+ ]