provide-foundation 0.0.0.dev1__py3-none-any.whl → 0.0.0.dev3__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.
- provide/foundation/__init__.py +36 -10
- provide/foundation/archive/__init__.py +1 -1
- provide/foundation/archive/base.py +15 -14
- provide/foundation/archive/bzip2.py +40 -40
- provide/foundation/archive/gzip.py +42 -42
- provide/foundation/archive/operations.py +93 -96
- provide/foundation/archive/tar.py +33 -31
- provide/foundation/archive/zip.py +52 -50
- provide/foundation/asynctools/__init__.py +20 -0
- provide/foundation/asynctools/core.py +126 -0
- provide/foundation/cli/__init__.py +2 -2
- provide/foundation/cli/commands/deps.py +15 -9
- provide/foundation/cli/commands/logs/__init__.py +3 -3
- provide/foundation/cli/commands/logs/generate.py +2 -2
- provide/foundation/cli/commands/logs/query.py +4 -4
- provide/foundation/cli/commands/logs/send.py +3 -3
- provide/foundation/cli/commands/logs/tail.py +3 -3
- provide/foundation/cli/decorators.py +11 -11
- provide/foundation/cli/main.py +1 -1
- provide/foundation/cli/testing.py +2 -40
- provide/foundation/cli/utils.py +21 -18
- provide/foundation/config/__init__.py +35 -2
- provide/foundation/config/base.py +2 -2
- provide/foundation/config/converters.py +477 -0
- provide/foundation/config/defaults.py +67 -0
- provide/foundation/config/env.py +6 -20
- provide/foundation/config/loader.py +10 -4
- provide/foundation/config/sync.py +8 -6
- provide/foundation/config/types.py +5 -5
- provide/foundation/config/validators.py +4 -4
- provide/foundation/console/input.py +5 -5
- provide/foundation/console/output.py +36 -14
- provide/foundation/context/__init__.py +8 -4
- provide/foundation/context/core.py +88 -110
- provide/foundation/crypto/certificates/__init__.py +9 -5
- provide/foundation/crypto/certificates/base.py +2 -2
- provide/foundation/crypto/certificates/certificate.py +48 -19
- provide/foundation/crypto/certificates/factory.py +26 -18
- provide/foundation/crypto/certificates/generator.py +24 -23
- provide/foundation/crypto/certificates/loader.py +24 -16
- provide/foundation/crypto/certificates/operations.py +17 -10
- provide/foundation/crypto/certificates/trust.py +21 -21
- provide/foundation/env/__init__.py +28 -0
- provide/foundation/env/core.py +218 -0
- provide/foundation/errors/__init__.py +3 -3
- provide/foundation/errors/decorators.py +0 -234
- provide/foundation/errors/types.py +0 -98
- provide/foundation/eventsets/display.py +13 -14
- provide/foundation/eventsets/registry.py +61 -31
- provide/foundation/eventsets/resolver.py +50 -46
- provide/foundation/eventsets/sets/das.py +8 -8
- provide/foundation/eventsets/sets/database.py +14 -14
- provide/foundation/eventsets/sets/http.py +21 -21
- provide/foundation/eventsets/sets/llm.py +16 -16
- provide/foundation/eventsets/sets/task_queue.py +13 -13
- provide/foundation/eventsets/types.py +7 -7
- provide/foundation/file/directory.py +14 -23
- provide/foundation/file/lock.py +4 -3
- provide/foundation/hub/components.py +75 -389
- provide/foundation/hub/config.py +157 -0
- provide/foundation/hub/discovery.py +63 -0
- provide/foundation/hub/handlers.py +89 -0
- provide/foundation/hub/lifecycle.py +195 -0
- provide/foundation/hub/manager.py +7 -4
- provide/foundation/hub/processors.py +49 -0
- provide/foundation/integrations/__init__.py +11 -0
- provide/foundation/{observability → integrations}/openobserve/__init__.py +10 -7
- provide/foundation/{observability → integrations}/openobserve/auth.py +1 -1
- provide/foundation/{observability → integrations}/openobserve/client.py +14 -14
- provide/foundation/{observability → integrations}/openobserve/commands.py +12 -12
- provide/foundation/integrations/openobserve/config.py +37 -0
- provide/foundation/{observability → integrations}/openobserve/formatters.py +1 -1
- provide/foundation/{observability → integrations}/openobserve/otlp.py +2 -2
- provide/foundation/{observability → integrations}/openobserve/search.py +2 -3
- provide/foundation/{observability → integrations}/openobserve/streaming.py +5 -5
- provide/foundation/logger/__init__.py +0 -1
- provide/foundation/logger/config/base.py +1 -1
- provide/foundation/logger/config/logging.py +69 -299
- provide/foundation/logger/config/telemetry.py +39 -121
- provide/foundation/logger/factories.py +2 -2
- provide/foundation/logger/processors/main.py +12 -10
- provide/foundation/logger/ratelimit/limiters.py +4 -4
- provide/foundation/logger/ratelimit/processor.py +1 -1
- provide/foundation/logger/setup/coordinator.py +39 -25
- provide/foundation/logger/setup/processors.py +3 -3
- provide/foundation/logger/setup/testing.py +14 -0
- provide/foundation/logger/trace.py +5 -5
- provide/foundation/metrics/__init__.py +1 -1
- provide/foundation/metrics/otel.py +3 -1
- provide/foundation/observability/__init__.py +3 -3
- provide/foundation/process/__init__.py +9 -0
- provide/foundation/process/exit.py +48 -0
- provide/foundation/process/lifecycle.py +69 -46
- provide/foundation/resilience/__init__.py +36 -0
- provide/foundation/resilience/circuit.py +166 -0
- provide/foundation/resilience/decorators.py +236 -0
- provide/foundation/resilience/fallback.py +208 -0
- provide/foundation/resilience/retry.py +327 -0
- provide/foundation/serialization/__init__.py +16 -0
- provide/foundation/serialization/core.py +70 -0
- provide/foundation/streams/config.py +78 -0
- provide/foundation/streams/console.py +4 -5
- provide/foundation/streams/core.py +5 -2
- provide/foundation/streams/file.py +12 -2
- provide/foundation/testing/__init__.py +29 -9
- provide/foundation/testing/archive/__init__.py +7 -7
- provide/foundation/testing/archive/fixtures.py +58 -54
- provide/foundation/testing/cli.py +30 -20
- provide/foundation/testing/common/__init__.py +13 -15
- provide/foundation/testing/common/fixtures.py +27 -57
- provide/foundation/testing/file/__init__.py +15 -15
- provide/foundation/testing/file/content_fixtures.py +289 -0
- provide/foundation/testing/file/directory_fixtures.py +107 -0
- provide/foundation/testing/file/fixtures.py +42 -516
- provide/foundation/testing/file/special_fixtures.py +145 -0
- provide/foundation/testing/logger.py +89 -8
- provide/foundation/testing/mocking/__init__.py +21 -21
- provide/foundation/testing/mocking/fixtures.py +80 -67
- provide/foundation/testing/process/__init__.py +23 -23
- provide/foundation/testing/process/async_fixtures.py +414 -0
- provide/foundation/testing/process/fixtures.py +48 -571
- provide/foundation/testing/process/subprocess_fixtures.py +210 -0
- provide/foundation/testing/threading/__init__.py +17 -17
- provide/foundation/testing/threading/basic_fixtures.py +105 -0
- provide/foundation/testing/threading/data_fixtures.py +101 -0
- provide/foundation/testing/threading/execution_fixtures.py +278 -0
- provide/foundation/testing/threading/fixtures.py +32 -502
- provide/foundation/testing/threading/sync_fixtures.py +100 -0
- provide/foundation/testing/time/__init__.py +11 -11
- provide/foundation/testing/time/fixtures.py +95 -83
- provide/foundation/testing/transport/__init__.py +9 -9
- provide/foundation/testing/transport/fixtures.py +54 -54
- provide/foundation/time/__init__.py +18 -0
- provide/foundation/time/core.py +63 -0
- provide/foundation/tools/__init__.py +2 -2
- provide/foundation/tools/base.py +68 -67
- provide/foundation/tools/cache.py +69 -74
- provide/foundation/tools/downloader.py +68 -62
- provide/foundation/tools/installer.py +51 -57
- provide/foundation/tools/registry.py +38 -45
- provide/foundation/tools/resolver.py +70 -68
- provide/foundation/tools/verifier.py +39 -50
- provide/foundation/tracer/spans.py +2 -14
- provide/foundation/transport/__init__.py +26 -33
- provide/foundation/transport/base.py +32 -30
- provide/foundation/transport/client.py +44 -49
- provide/foundation/transport/config.py +36 -107
- provide/foundation/transport/errors.py +13 -27
- provide/foundation/transport/http.py +69 -55
- provide/foundation/transport/middleware.py +113 -114
- provide/foundation/transport/registry.py +29 -27
- provide/foundation/transport/types.py +6 -6
- provide/foundation/utils/deps.py +17 -14
- provide/foundation/utils/parsing.py +49 -4
- {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/METADATA +2 -2
- provide_foundation-0.0.0.dev3.dist-info/RECORD +233 -0
- provide_foundation-0.0.0.dev1.dist-info/RECORD +0 -200
- /provide/foundation/{observability → integrations}/openobserve/exceptions.py +0 -0
- /provide/foundation/{observability → integrations}/openobserve/models.py +0 -0
- {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/WHEEL +0 -0
- {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/entry_points.txt +0 -0
- {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/licenses/LICENSE +0 -0
- {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/top_level.txt +0 -0
provide/foundation/tools/base.py
CHANGED
@@ -7,7 +7,6 @@ the base manager class and metadata structures.
|
|
7
7
|
|
8
8
|
from abc import ABC, abstractmethod
|
9
9
|
from pathlib import Path
|
10
|
-
from typing import Any
|
11
10
|
|
12
11
|
from attrs import define, field
|
13
12
|
|
@@ -20,25 +19,25 @@ log = get_logger(__name__)
|
|
20
19
|
|
21
20
|
class ToolError(FoundationError):
|
22
21
|
"""Base exception for tool-related errors."""
|
23
|
-
|
22
|
+
|
24
23
|
pass
|
25
24
|
|
26
25
|
|
27
26
|
class ToolNotFoundError(ToolError):
|
28
27
|
"""Raised when a tool or version cannot be found."""
|
29
|
-
|
28
|
+
|
30
29
|
pass
|
31
30
|
|
32
31
|
|
33
32
|
class ToolInstallError(ToolError):
|
34
33
|
"""Raised when tool installation fails."""
|
35
|
-
|
34
|
+
|
36
35
|
pass
|
37
36
|
|
38
37
|
|
39
38
|
class ToolVerificationError(ToolError):
|
40
39
|
"""Raised when tool verification fails."""
|
41
|
-
|
40
|
+
|
42
41
|
pass
|
43
42
|
|
44
43
|
|
@@ -46,7 +45,7 @@ class ToolVerificationError(ToolError):
|
|
46
45
|
class ToolMetadata:
|
47
46
|
"""
|
48
47
|
Metadata about a tool version.
|
49
|
-
|
48
|
+
|
50
49
|
Attributes:
|
51
50
|
name: Tool name (e.g., "terraform").
|
52
51
|
version: Version string (e.g., "1.5.0").
|
@@ -61,7 +60,7 @@ class ToolMetadata:
|
|
61
60
|
dependencies: Other tools this depends on.
|
62
61
|
executable_name: Name of the executable file.
|
63
62
|
"""
|
64
|
-
|
63
|
+
|
65
64
|
name: str
|
66
65
|
version: str
|
67
66
|
platform: str
|
@@ -79,26 +78,26 @@ class ToolMetadata:
|
|
79
78
|
class BaseToolManager(ABC):
|
80
79
|
"""
|
81
80
|
Abstract base class for tool managers.
|
82
|
-
|
81
|
+
|
83
82
|
Provides common functionality for downloading, verifying, and installing
|
84
83
|
development tools. Subclasses must implement platform-specific logic.
|
85
|
-
|
84
|
+
|
86
85
|
Attributes:
|
87
86
|
config: Configuration object.
|
88
87
|
tool_name: Name of the tool being managed.
|
89
88
|
executable_name: Name of the executable file.
|
90
89
|
supported_platforms: List of supported platforms.
|
91
90
|
"""
|
92
|
-
|
91
|
+
|
93
92
|
# Class attributes to be overridden by subclasses
|
94
93
|
tool_name: str = ""
|
95
94
|
executable_name: str = ""
|
96
95
|
supported_platforms: list[str] = ["linux", "darwin", "windows"]
|
97
|
-
|
96
|
+
|
98
97
|
def __init__(self, config: BaseConfig):
|
99
98
|
"""
|
100
99
|
Initialize the tool manager.
|
101
|
-
|
100
|
+
|
102
101
|
Args:
|
103
102
|
config: Configuration object containing settings.
|
104
103
|
"""
|
@@ -106,149 +105,150 @@ class BaseToolManager(ABC):
|
|
106
105
|
raise ToolError("Subclass must define tool_name")
|
107
106
|
if not self.executable_name:
|
108
107
|
raise ToolError("Subclass must define executable_name")
|
109
|
-
|
108
|
+
|
110
109
|
self.config = config
|
111
|
-
|
110
|
+
|
112
111
|
# Lazy-load components to avoid circular imports
|
113
112
|
self._cache = None
|
114
113
|
self._downloader = None
|
115
114
|
self._verifier = None
|
116
115
|
self._installer = None
|
117
116
|
self._resolver = None
|
118
|
-
|
117
|
+
|
119
118
|
log.debug(f"Initialized {self.tool_name} manager")
|
120
|
-
|
119
|
+
|
121
120
|
@property
|
122
121
|
def cache(self):
|
123
122
|
"""Get or create cache instance."""
|
124
123
|
if self._cache is None:
|
125
124
|
from provide.foundation.tools.cache import ToolCache
|
125
|
+
|
126
126
|
self._cache = ToolCache()
|
127
127
|
return self._cache
|
128
|
-
|
128
|
+
|
129
129
|
@property
|
130
130
|
def downloader(self):
|
131
131
|
"""Get or create downloader instance."""
|
132
132
|
if self._downloader is None:
|
133
133
|
from provide.foundation.tools.downloader import ToolDownloader
|
134
134
|
from provide.foundation.transport import UniversalClient
|
135
|
+
|
135
136
|
self._downloader = ToolDownloader(UniversalClient())
|
136
137
|
return self._downloader
|
137
|
-
|
138
|
+
|
138
139
|
@property
|
139
140
|
def verifier(self):
|
140
141
|
"""Get or create verifier instance."""
|
141
142
|
if self._verifier is None:
|
142
143
|
from provide.foundation.tools.verifier import ToolVerifier
|
144
|
+
|
143
145
|
self._verifier = ToolVerifier()
|
144
146
|
return self._verifier
|
145
|
-
|
147
|
+
|
146
148
|
@property
|
147
149
|
def installer(self):
|
148
150
|
"""Get or create installer instance."""
|
149
151
|
if self._installer is None:
|
150
152
|
from provide.foundation.tools.installer import ToolInstaller
|
153
|
+
|
151
154
|
self._installer = ToolInstaller()
|
152
155
|
return self._installer
|
153
|
-
|
156
|
+
|
154
157
|
@property
|
155
158
|
def resolver(self):
|
156
159
|
"""Get or create version resolver instance."""
|
157
160
|
if self._resolver is None:
|
158
161
|
from provide.foundation.tools.resolver import VersionResolver
|
162
|
+
|
159
163
|
self._resolver = VersionResolver()
|
160
164
|
return self._resolver
|
161
|
-
|
165
|
+
|
162
166
|
@abstractmethod
|
163
167
|
def get_metadata(self, version: str) -> ToolMetadata:
|
164
168
|
"""
|
165
169
|
Get metadata for a specific version.
|
166
|
-
|
170
|
+
|
167
171
|
Args:
|
168
172
|
version: Version string to get metadata for.
|
169
|
-
|
173
|
+
|
170
174
|
Returns:
|
171
175
|
ToolMetadata object with download URLs and checksums.
|
172
176
|
"""
|
173
177
|
pass
|
174
|
-
|
178
|
+
|
175
179
|
@abstractmethod
|
176
180
|
def get_available_versions(self) -> list[str]:
|
177
181
|
"""
|
178
182
|
Get list of available versions from upstream.
|
179
|
-
|
183
|
+
|
180
184
|
Returns:
|
181
185
|
List of version strings available for download.
|
182
186
|
"""
|
183
187
|
pass
|
184
|
-
|
188
|
+
|
185
189
|
def resolve_version(self, spec: str) -> str:
|
186
190
|
"""
|
187
191
|
Resolve a version specification to a concrete version.
|
188
|
-
|
192
|
+
|
189
193
|
Args:
|
190
194
|
spec: Version specification (e.g., "latest", "~1.5.0").
|
191
|
-
|
195
|
+
|
192
196
|
Returns:
|
193
197
|
Concrete version string.
|
194
|
-
|
198
|
+
|
195
199
|
Raises:
|
196
200
|
ToolNotFoundError: If version cannot be resolved.
|
197
201
|
"""
|
198
202
|
available = self.get_available_versions()
|
199
203
|
if not available:
|
200
204
|
raise ToolNotFoundError(f"No versions available for {self.tool_name}")
|
201
|
-
|
205
|
+
|
202
206
|
resolved = self.resolver.resolve(spec, available)
|
203
207
|
if not resolved:
|
204
208
|
raise ToolNotFoundError(
|
205
209
|
f"Cannot resolve version '{spec}' for {self.tool_name}"
|
206
210
|
)
|
207
|
-
|
211
|
+
|
208
212
|
log.debug(f"Resolved {self.tool_name} version {spec} to {resolved}")
|
209
213
|
return resolved
|
210
|
-
|
214
|
+
|
211
215
|
def install(self, version: str = "latest", force: bool = False) -> Path:
|
212
216
|
"""
|
213
217
|
Install a specific version of the tool.
|
214
|
-
|
218
|
+
|
215
219
|
Args:
|
216
220
|
version: Version to install (default: "latest").
|
217
221
|
force: Force reinstall even if cached.
|
218
|
-
|
222
|
+
|
219
223
|
Returns:
|
220
224
|
Path to the installed tool.
|
221
|
-
|
225
|
+
|
222
226
|
Raises:
|
223
227
|
ToolInstallError: If installation fails.
|
224
228
|
"""
|
225
229
|
# Resolve version
|
226
230
|
if version in ["latest", "stable", "dev"] or version.startswith(("~", "^")):
|
227
231
|
version = self.resolve_version(version)
|
228
|
-
|
232
|
+
|
229
233
|
# Check cache unless forced
|
230
234
|
if not force:
|
231
235
|
if cached_path := self.cache.get(self.tool_name, version):
|
232
236
|
log.info(f"Using cached {self.tool_name} {version}")
|
233
237
|
return cached_path
|
234
|
-
|
238
|
+
|
235
239
|
log.info(f"Installing {self.tool_name} {version}")
|
236
|
-
|
240
|
+
|
237
241
|
# Get metadata
|
238
242
|
metadata = self.get_metadata(version)
|
239
243
|
if not metadata.download_url:
|
240
|
-
raise ToolInstallError(
|
241
|
-
|
242
|
-
)
|
243
|
-
|
244
|
+
raise ToolInstallError(f"No download URL for {self.tool_name} {version}")
|
245
|
+
|
244
246
|
# Download
|
245
247
|
download_path = Path("/tmp") / f"{self.tool_name}-{version}"
|
246
248
|
artifact_path = self.downloader.download_with_progress(
|
247
|
-
metadata.download_url,
|
248
|
-
download_path,
|
249
|
-
metadata.checksum
|
249
|
+
metadata.download_url, download_path, metadata.checksum
|
250
250
|
)
|
251
|
-
|
251
|
+
|
252
252
|
# Verify if checksum provided
|
253
253
|
if metadata.checksum:
|
254
254
|
if not self.verifier.verify_checksum(artifact_path, metadata.checksum):
|
@@ -256,79 +256,80 @@ class BaseToolManager(ABC):
|
|
256
256
|
raise ToolVerificationError(
|
257
257
|
f"Checksum verification failed for {self.tool_name} {version}"
|
258
258
|
)
|
259
|
-
|
259
|
+
|
260
260
|
# Install
|
261
261
|
install_path = self.installer.install(artifact_path, metadata)
|
262
|
-
|
262
|
+
|
263
263
|
# Cache the installation
|
264
264
|
self.cache.store(self.tool_name, version, install_path)
|
265
|
-
|
265
|
+
|
266
266
|
# Clean up download
|
267
267
|
if artifact_path.exists():
|
268
268
|
artifact_path.unlink()
|
269
|
-
|
269
|
+
|
270
270
|
log.info(f"Successfully installed {self.tool_name} {version} to {install_path}")
|
271
271
|
return install_path
|
272
|
-
|
272
|
+
|
273
273
|
def uninstall(self, version: str) -> bool:
|
274
274
|
"""
|
275
275
|
Uninstall a specific version.
|
276
|
-
|
276
|
+
|
277
277
|
Args:
|
278
278
|
version: Version to uninstall.
|
279
|
-
|
279
|
+
|
280
280
|
Returns:
|
281
281
|
True if uninstalled, False if not found.
|
282
282
|
"""
|
283
283
|
# Invalidate cache
|
284
284
|
self.cache.invalidate(self.tool_name, version)
|
285
|
-
|
285
|
+
|
286
286
|
# Remove from filesystem
|
287
287
|
install_path = self.get_install_path(version)
|
288
288
|
if install_path.exists():
|
289
289
|
import shutil
|
290
|
+
|
290
291
|
shutil.rmtree(install_path)
|
291
292
|
log.info(f"Uninstalled {self.tool_name} {version}")
|
292
293
|
return True
|
293
|
-
|
294
|
+
|
294
295
|
return False
|
295
|
-
|
296
|
+
|
296
297
|
def get_install_path(self, version: str) -> Path:
|
297
298
|
"""
|
298
299
|
Get the installation path for a version.
|
299
|
-
|
300
|
+
|
300
301
|
Args:
|
301
302
|
version: Version string.
|
302
|
-
|
303
|
+
|
303
304
|
Returns:
|
304
305
|
Path where the version is/will be installed.
|
305
306
|
"""
|
306
307
|
base_path = Path.home() / ".wrknv" / "tools" / self.tool_name / version
|
307
308
|
return base_path
|
308
|
-
|
309
|
+
|
309
310
|
def is_installed(self, version: str) -> bool:
|
310
311
|
"""
|
311
312
|
Check if a version is installed.
|
312
|
-
|
313
|
+
|
313
314
|
Args:
|
314
315
|
version: Version to check.
|
315
|
-
|
316
|
+
|
316
317
|
Returns:
|
317
318
|
True if installed, False otherwise.
|
318
319
|
"""
|
319
320
|
install_path = self.get_install_path(version)
|
320
321
|
executable = install_path / "bin" / self.executable_name
|
321
322
|
return executable.exists()
|
322
|
-
|
323
|
+
|
323
324
|
def get_platform_info(self) -> dict[str, str]:
|
324
325
|
"""
|
325
326
|
Get current platform information.
|
326
|
-
|
327
|
+
|
327
328
|
Returns:
|
328
329
|
Dictionary with platform and arch keys.
|
329
330
|
"""
|
330
331
|
import platform
|
331
|
-
|
332
|
+
|
332
333
|
system = platform.system().lower()
|
333
334
|
if system == "darwin":
|
334
335
|
system = "darwin"
|
@@ -336,7 +337,7 @@ class BaseToolManager(ABC):
|
|
336
337
|
system = "linux"
|
337
338
|
elif system == "windows":
|
338
339
|
system = "windows"
|
339
|
-
|
340
|
+
|
340
341
|
machine = platform.machine().lower()
|
341
342
|
if machine in ["x86_64", "amd64"]:
|
342
343
|
arch = "amd64"
|
@@ -344,5 +345,5 @@ class BaseToolManager(ABC):
|
|
344
345
|
arch = "arm64"
|
345
346
|
else:
|
346
347
|
arch = machine
|
347
|
-
|
348
|
-
return {"platform": system, "arch": arch}
|
348
|
+
|
349
|
+
return {"platform": system, "arch": arch}
|