kstlib 0.0.1a0__py3-none-any.whl → 1.0.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 (166) hide show
  1. kstlib/__init__.py +266 -1
  2. kstlib/__main__.py +16 -0
  3. kstlib/alerts/__init__.py +110 -0
  4. kstlib/alerts/channels/__init__.py +36 -0
  5. kstlib/alerts/channels/base.py +197 -0
  6. kstlib/alerts/channels/email.py +227 -0
  7. kstlib/alerts/channels/slack.py +389 -0
  8. kstlib/alerts/exceptions.py +72 -0
  9. kstlib/alerts/manager.py +651 -0
  10. kstlib/alerts/models.py +142 -0
  11. kstlib/alerts/throttle.py +263 -0
  12. kstlib/auth/__init__.py +139 -0
  13. kstlib/auth/callback.py +399 -0
  14. kstlib/auth/config.py +502 -0
  15. kstlib/auth/errors.py +127 -0
  16. kstlib/auth/models.py +316 -0
  17. kstlib/auth/providers/__init__.py +14 -0
  18. kstlib/auth/providers/base.py +393 -0
  19. kstlib/auth/providers/oauth2.py +645 -0
  20. kstlib/auth/providers/oidc.py +821 -0
  21. kstlib/auth/session.py +338 -0
  22. kstlib/auth/token.py +482 -0
  23. kstlib/cache/__init__.py +50 -0
  24. kstlib/cache/decorator.py +261 -0
  25. kstlib/cache/strategies.py +516 -0
  26. kstlib/cli/__init__.py +8 -0
  27. kstlib/cli/app.py +195 -0
  28. kstlib/cli/commands/__init__.py +5 -0
  29. kstlib/cli/commands/auth/__init__.py +39 -0
  30. kstlib/cli/commands/auth/common.py +122 -0
  31. kstlib/cli/commands/auth/login.py +325 -0
  32. kstlib/cli/commands/auth/logout.py +74 -0
  33. kstlib/cli/commands/auth/providers.py +57 -0
  34. kstlib/cli/commands/auth/status.py +291 -0
  35. kstlib/cli/commands/auth/token.py +199 -0
  36. kstlib/cli/commands/auth/whoami.py +106 -0
  37. kstlib/cli/commands/config.py +89 -0
  38. kstlib/cli/commands/ops/__init__.py +39 -0
  39. kstlib/cli/commands/ops/attach.py +49 -0
  40. kstlib/cli/commands/ops/common.py +269 -0
  41. kstlib/cli/commands/ops/list_sessions.py +252 -0
  42. kstlib/cli/commands/ops/logs.py +49 -0
  43. kstlib/cli/commands/ops/start.py +98 -0
  44. kstlib/cli/commands/ops/status.py +138 -0
  45. kstlib/cli/commands/ops/stop.py +60 -0
  46. kstlib/cli/commands/rapi/__init__.py +60 -0
  47. kstlib/cli/commands/rapi/call.py +341 -0
  48. kstlib/cli/commands/rapi/list.py +99 -0
  49. kstlib/cli/commands/rapi/show.py +206 -0
  50. kstlib/cli/commands/secrets/__init__.py +35 -0
  51. kstlib/cli/commands/secrets/common.py +425 -0
  52. kstlib/cli/commands/secrets/decrypt.py +88 -0
  53. kstlib/cli/commands/secrets/doctor.py +743 -0
  54. kstlib/cli/commands/secrets/encrypt.py +242 -0
  55. kstlib/cli/commands/secrets/shred.py +96 -0
  56. kstlib/cli/common.py +86 -0
  57. kstlib/config/__init__.py +76 -0
  58. kstlib/config/exceptions.py +110 -0
  59. kstlib/config/export.py +225 -0
  60. kstlib/config/loader.py +963 -0
  61. kstlib/config/sops.py +287 -0
  62. kstlib/db/__init__.py +54 -0
  63. kstlib/db/aiosqlcipher.py +137 -0
  64. kstlib/db/cipher.py +112 -0
  65. kstlib/db/database.py +367 -0
  66. kstlib/db/exceptions.py +25 -0
  67. kstlib/db/pool.py +302 -0
  68. kstlib/helpers/__init__.py +35 -0
  69. kstlib/helpers/exceptions.py +11 -0
  70. kstlib/helpers/time_trigger.py +396 -0
  71. kstlib/kstlib.conf.yml +890 -0
  72. kstlib/limits.py +963 -0
  73. kstlib/logging/__init__.py +108 -0
  74. kstlib/logging/manager.py +633 -0
  75. kstlib/mail/__init__.py +42 -0
  76. kstlib/mail/builder.py +626 -0
  77. kstlib/mail/exceptions.py +27 -0
  78. kstlib/mail/filesystem.py +248 -0
  79. kstlib/mail/transport.py +224 -0
  80. kstlib/mail/transports/__init__.py +19 -0
  81. kstlib/mail/transports/gmail.py +268 -0
  82. kstlib/mail/transports/resend.py +324 -0
  83. kstlib/mail/transports/smtp.py +326 -0
  84. kstlib/meta.py +72 -0
  85. kstlib/metrics/__init__.py +88 -0
  86. kstlib/metrics/decorators.py +1090 -0
  87. kstlib/metrics/exceptions.py +14 -0
  88. kstlib/monitoring/__init__.py +116 -0
  89. kstlib/monitoring/_styles.py +163 -0
  90. kstlib/monitoring/cell.py +57 -0
  91. kstlib/monitoring/config.py +424 -0
  92. kstlib/monitoring/delivery.py +579 -0
  93. kstlib/monitoring/exceptions.py +63 -0
  94. kstlib/monitoring/image.py +220 -0
  95. kstlib/monitoring/kv.py +79 -0
  96. kstlib/monitoring/list.py +69 -0
  97. kstlib/monitoring/metric.py +88 -0
  98. kstlib/monitoring/monitoring.py +341 -0
  99. kstlib/monitoring/renderer.py +139 -0
  100. kstlib/monitoring/service.py +392 -0
  101. kstlib/monitoring/table.py +129 -0
  102. kstlib/monitoring/types.py +56 -0
  103. kstlib/ops/__init__.py +86 -0
  104. kstlib/ops/base.py +148 -0
  105. kstlib/ops/container.py +577 -0
  106. kstlib/ops/exceptions.py +209 -0
  107. kstlib/ops/manager.py +407 -0
  108. kstlib/ops/models.py +176 -0
  109. kstlib/ops/tmux.py +372 -0
  110. kstlib/ops/validators.py +287 -0
  111. kstlib/py.typed +0 -0
  112. kstlib/rapi/__init__.py +118 -0
  113. kstlib/rapi/client.py +875 -0
  114. kstlib/rapi/config.py +861 -0
  115. kstlib/rapi/credentials.py +887 -0
  116. kstlib/rapi/exceptions.py +213 -0
  117. kstlib/resilience/__init__.py +101 -0
  118. kstlib/resilience/circuit_breaker.py +440 -0
  119. kstlib/resilience/exceptions.py +95 -0
  120. kstlib/resilience/heartbeat.py +491 -0
  121. kstlib/resilience/rate_limiter.py +506 -0
  122. kstlib/resilience/shutdown.py +417 -0
  123. kstlib/resilience/watchdog.py +637 -0
  124. kstlib/secrets/__init__.py +29 -0
  125. kstlib/secrets/exceptions.py +19 -0
  126. kstlib/secrets/models.py +62 -0
  127. kstlib/secrets/providers/__init__.py +79 -0
  128. kstlib/secrets/providers/base.py +58 -0
  129. kstlib/secrets/providers/environment.py +66 -0
  130. kstlib/secrets/providers/keyring.py +107 -0
  131. kstlib/secrets/providers/kms.py +223 -0
  132. kstlib/secrets/providers/kwargs.py +101 -0
  133. kstlib/secrets/providers/sops.py +209 -0
  134. kstlib/secrets/resolver.py +221 -0
  135. kstlib/secrets/sensitive.py +130 -0
  136. kstlib/secure/__init__.py +23 -0
  137. kstlib/secure/fs.py +194 -0
  138. kstlib/secure/permissions.py +70 -0
  139. kstlib/ssl.py +347 -0
  140. kstlib/ui/__init__.py +23 -0
  141. kstlib/ui/exceptions.py +26 -0
  142. kstlib/ui/panels.py +484 -0
  143. kstlib/ui/spinner.py +864 -0
  144. kstlib/ui/tables.py +382 -0
  145. kstlib/utils/__init__.py +48 -0
  146. kstlib/utils/dict.py +36 -0
  147. kstlib/utils/formatting.py +338 -0
  148. kstlib/utils/http_trace.py +237 -0
  149. kstlib/utils/lazy.py +49 -0
  150. kstlib/utils/secure_delete.py +205 -0
  151. kstlib/utils/serialization.py +247 -0
  152. kstlib/utils/text.py +56 -0
  153. kstlib/utils/validators.py +124 -0
  154. kstlib/websocket/__init__.py +97 -0
  155. kstlib/websocket/exceptions.py +214 -0
  156. kstlib/websocket/manager.py +1102 -0
  157. kstlib/websocket/models.py +361 -0
  158. kstlib-1.0.1.dist-info/METADATA +201 -0
  159. kstlib-1.0.1.dist-info/RECORD +163 -0
  160. {kstlib-0.0.1a0.dist-info → kstlib-1.0.1.dist-info}/WHEEL +1 -1
  161. kstlib-1.0.1.dist-info/entry_points.txt +2 -0
  162. kstlib-1.0.1.dist-info/licenses/LICENSE.md +9 -0
  163. kstlib-0.0.1a0.dist-info/METADATA +0 -29
  164. kstlib-0.0.1a0.dist-info/RECORD +0 -6
  165. kstlib-0.0.1a0.dist-info/licenses/LICENSE.md +0 -5
  166. {kstlib-0.0.1a0.dist-info → kstlib-1.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,261 @@
1
+ """Caching decorator with config-based strategy selection.
2
+
3
+ Provides @cache decorator with automatic async/sync detection
4
+ and configuration priority chain.
5
+ """
6
+
7
+ # pylint: disable=too-many-arguments
8
+
9
+ import functools
10
+ import inspect
11
+ from collections.abc import Callable
12
+ from typing import Any, TypeVar, overload
13
+
14
+ from kstlib.cache.strategies import (
15
+ CacheStrategy,
16
+ FileCacheStrategy,
17
+ LRUCacheStrategy,
18
+ TTLCacheStrategy,
19
+ )
20
+ from kstlib.config import get_config
21
+ from kstlib.config.exceptions import ConfigFileNotFoundError
22
+
23
+ F = TypeVar("F", bound=Callable[..., Any])
24
+
25
+
26
+ def _get_cache_config() -> dict[str, Any]:
27
+ """Get cache configuration from kstlib config.
28
+
29
+ Returns:
30
+ Cache configuration dict with defaults
31
+ """
32
+ try:
33
+ config = get_config()
34
+ if hasattr(config, "cache"):
35
+ return dict(config.cache)
36
+ except (AttributeError, ImportError, ConfigFileNotFoundError):
37
+ # Config not available or cache section missing
38
+ pass
39
+
40
+ # Fallback defaults
41
+ return {
42
+ "default_strategy": "ttl",
43
+ "ttl": {"default_seconds": 300, "max_entries": 1000, "cleanup_interval": 60},
44
+ "lru": {"maxsize": 128, "typed": False},
45
+ "file": {"enabled": True, "cache_dir": ".cache", "check_mtime": True, "serializer": "json"},
46
+ "async_support": {"enabled": True, "executor_workers": 4},
47
+ }
48
+
49
+
50
+ def _create_strategy(
51
+ strategy: str | None = None,
52
+ *,
53
+ ttl: int | None = None,
54
+ maxsize: int | None = None,
55
+ cache_dir: str | None = None,
56
+ check_mtime: bool | None = None,
57
+ serializer: str | None = None,
58
+ ) -> CacheStrategy:
59
+ """Create cache strategy based on parameters and config.
60
+
61
+ Args:
62
+ strategy: Strategy name ('ttl', 'lru', 'file')
63
+ ttl: TTL in seconds (for TTL strategy)
64
+ maxsize: Max cache size (for LRU strategy)
65
+ cache_dir: Cache directory (for file strategy)
66
+ check_mtime: Check file mtime (for file strategy)
67
+ serializer: Serializer name for the file strategy ('json', 'pickle', 'auto')
68
+
69
+ Returns:
70
+ Configured cache strategy instance
71
+ """
72
+ config = _get_cache_config()
73
+
74
+ # Determine strategy (argument > config)
75
+ strategy_name = strategy or config.get("default_strategy", "ttl")
76
+
77
+ if strategy_name == "ttl":
78
+ ttl_config = config.get("ttl", {})
79
+ return TTLCacheStrategy(
80
+ ttl=ttl or ttl_config.get("default_seconds", 300),
81
+ max_entries=ttl_config.get("max_entries", 1000),
82
+ cleanup_interval=ttl_config.get("cleanup_interval", 60),
83
+ )
84
+
85
+ if strategy_name == "lru":
86
+ lru_config = config.get("lru", {})
87
+ return LRUCacheStrategy(
88
+ maxsize=maxsize or lru_config.get("maxsize", 128),
89
+ typed=lru_config.get("typed", False),
90
+ )
91
+
92
+ if strategy_name == "file":
93
+ file_config = config.get("file", {})
94
+ return FileCacheStrategy(
95
+ cache_dir=cache_dir or file_config.get("cache_dir", ".cache"),
96
+ check_mtime=check_mtime if check_mtime is not None else file_config.get("check_mtime", True),
97
+ serializer=serializer or file_config.get("serializer", "json"),
98
+ )
99
+
100
+ # Fallback to TTL
101
+ return TTLCacheStrategy()
102
+
103
+
104
+ @overload
105
+ def cache(func: F) -> F: ...
106
+
107
+
108
+ @overload
109
+ def cache(
110
+ *,
111
+ strategy: str | None = None,
112
+ ttl: int | None = None,
113
+ maxsize: int | None = None,
114
+ cache_dir: str | None = None,
115
+ check_mtime: bool | None = None,
116
+ serializer: str | None = None,
117
+ ) -> Callable[[F], F]: ...
118
+
119
+
120
+ def cache(
121
+ func: F | None = None,
122
+ *,
123
+ strategy: str | None = None,
124
+ ttl: int | None = None,
125
+ maxsize: int | None = None,
126
+ cache_dir: str | None = None,
127
+ check_mtime: bool | None = None,
128
+ serializer: str | None = None,
129
+ ) -> F | Callable[[F], F]:
130
+ """Cache decorator with automatic async/sync detection.
131
+
132
+ Supports multiple caching strategies configured via kstlib.conf.yml
133
+ or decorator arguments. Automatically detects async functions and
134
+ handles them appropriately.
135
+
136
+ Args:
137
+ func: Function to cache (when used without parentheses)
138
+ strategy: Cache strategy ('ttl', 'lru', 'file')
139
+ ttl: Time to live in seconds (TTL strategy)
140
+ maxsize: Maximum cache size (LRU strategy)
141
+ cache_dir: Cache directory path (file strategy)
142
+ check_mtime: Check file modification time (file strategy)
143
+ serializer: Serialization format for file strategy ('json', 'pickle', 'auto')
144
+
145
+ Returns:
146
+ Decorated function with caching
147
+
148
+ Examples:
149
+ Basic usage (uses config defaults):
150
+
151
+ >>> @cache
152
+ ... def double(x: int) -> int:
153
+ ... return x * 2
154
+ >>> double(5)
155
+ 10
156
+ >>> double(5) # Returns cached value
157
+ 10
158
+
159
+ With explicit TTL strategy:
160
+
161
+ >>> @cache(strategy="ttl", ttl=60)
162
+ ... def compute(n: int) -> int:
163
+ ... return n * n
164
+ >>> compute(4)
165
+ 16
166
+
167
+ LRU cache for recursive functions:
168
+
169
+ >>> @cache(strategy="lru", maxsize=128)
170
+ ... def fibonacci(n: int) -> int:
171
+ ... if n < 2:
172
+ ... return n
173
+ ... return fibonacci(n - 1) + fibonacci(n - 2)
174
+ >>> fibonacci(10)
175
+ 55
176
+
177
+ Cache management methods:
178
+
179
+ >>> double.cache_info()
180
+ {'strategy': 'ttl', 'is_async': False}
181
+ >>> double.cache_clear() # Clear cached values
182
+ """
183
+
184
+ def decorator(f: F) -> F:
185
+ # Create strategy instance
186
+ cache_strategy = _create_strategy(
187
+ strategy=strategy,
188
+ ttl=ttl,
189
+ maxsize=maxsize,
190
+ cache_dir=cache_dir,
191
+ check_mtime=check_mtime,
192
+ serializer=serializer,
193
+ )
194
+
195
+ # Check if function is async
196
+ is_async = inspect.iscoroutinefunction(f)
197
+
198
+ if is_async:
199
+ # Async wrapper
200
+ @functools.wraps(f)
201
+ async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
202
+ # Generate cache key
203
+ cache_key = cache_strategy.make_key(f, args, kwargs)
204
+
205
+ # Check cache
206
+ cached_value = cache_strategy.get(cache_key)
207
+ if cached_value is not None:
208
+ return cached_value
209
+
210
+ # Call async function
211
+ result = await f(*args, **kwargs)
212
+
213
+ # Store in cache
214
+ cache_strategy.set(cache_key, result)
215
+
216
+ return result
217
+
218
+ # Add cache management methods
219
+ async_wrapper.cache_clear = cache_strategy.clear # type: ignore[attr-defined]
220
+
221
+ def _async_cache_info() -> dict[str, Any]:
222
+ return {"strategy": strategy or "ttl", "is_async": True}
223
+
224
+ async_wrapper.cache_info = _async_cache_info # type: ignore[attr-defined]
225
+
226
+ return async_wrapper # type: ignore[return-value]
227
+
228
+ # Sync wrapper
229
+ @functools.wraps(f)
230
+ def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
231
+ # Generate cache key
232
+ cache_key = cache_strategy.make_key(f, args, kwargs)
233
+
234
+ # Check cache
235
+ cached_value = cache_strategy.get(cache_key)
236
+ if cached_value is not None:
237
+ return cached_value
238
+
239
+ # Call function
240
+ result = f(*args, **kwargs)
241
+
242
+ # Store in cache
243
+ cache_strategy.set(cache_key, result)
244
+
245
+ return result
246
+
247
+ # Add cache management methods
248
+ sync_wrapper.cache_clear = cache_strategy.clear # type: ignore[attr-defined]
249
+
250
+ def _sync_cache_info() -> dict[str, Any]:
251
+ return {"strategy": strategy or "ttl", "is_async": False}
252
+
253
+ sync_wrapper.cache_info = _sync_cache_info # type: ignore[attr-defined]
254
+
255
+ return sync_wrapper # type: ignore[return-value]
256
+
257
+ # Handle both @cache and @cache(...) syntax
258
+ if func is not None:
259
+ return decorator(func)
260
+
261
+ return decorator