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.
Files changed (163) hide show
  1. provide/foundation/__init__.py +36 -10
  2. provide/foundation/archive/__init__.py +1 -1
  3. provide/foundation/archive/base.py +15 -14
  4. provide/foundation/archive/bzip2.py +40 -40
  5. provide/foundation/archive/gzip.py +42 -42
  6. provide/foundation/archive/operations.py +93 -96
  7. provide/foundation/archive/tar.py +33 -31
  8. provide/foundation/archive/zip.py +52 -50
  9. provide/foundation/asynctools/__init__.py +20 -0
  10. provide/foundation/asynctools/core.py +126 -0
  11. provide/foundation/cli/__init__.py +2 -2
  12. provide/foundation/cli/commands/deps.py +15 -9
  13. provide/foundation/cli/commands/logs/__init__.py +3 -3
  14. provide/foundation/cli/commands/logs/generate.py +2 -2
  15. provide/foundation/cli/commands/logs/query.py +4 -4
  16. provide/foundation/cli/commands/logs/send.py +3 -3
  17. provide/foundation/cli/commands/logs/tail.py +3 -3
  18. provide/foundation/cli/decorators.py +11 -11
  19. provide/foundation/cli/main.py +1 -1
  20. provide/foundation/cli/testing.py +2 -40
  21. provide/foundation/cli/utils.py +21 -18
  22. provide/foundation/config/__init__.py +35 -2
  23. provide/foundation/config/base.py +2 -2
  24. provide/foundation/config/converters.py +477 -0
  25. provide/foundation/config/defaults.py +67 -0
  26. provide/foundation/config/env.py +6 -20
  27. provide/foundation/config/loader.py +10 -4
  28. provide/foundation/config/sync.py +8 -6
  29. provide/foundation/config/types.py +5 -5
  30. provide/foundation/config/validators.py +4 -4
  31. provide/foundation/console/input.py +5 -5
  32. provide/foundation/console/output.py +36 -14
  33. provide/foundation/context/__init__.py +8 -4
  34. provide/foundation/context/core.py +88 -110
  35. provide/foundation/crypto/certificates/__init__.py +9 -5
  36. provide/foundation/crypto/certificates/base.py +2 -2
  37. provide/foundation/crypto/certificates/certificate.py +48 -19
  38. provide/foundation/crypto/certificates/factory.py +26 -18
  39. provide/foundation/crypto/certificates/generator.py +24 -23
  40. provide/foundation/crypto/certificates/loader.py +24 -16
  41. provide/foundation/crypto/certificates/operations.py +17 -10
  42. provide/foundation/crypto/certificates/trust.py +21 -21
  43. provide/foundation/env/__init__.py +28 -0
  44. provide/foundation/env/core.py +218 -0
  45. provide/foundation/errors/__init__.py +3 -3
  46. provide/foundation/errors/decorators.py +0 -234
  47. provide/foundation/errors/types.py +0 -98
  48. provide/foundation/eventsets/display.py +13 -14
  49. provide/foundation/eventsets/registry.py +61 -31
  50. provide/foundation/eventsets/resolver.py +50 -46
  51. provide/foundation/eventsets/sets/das.py +8 -8
  52. provide/foundation/eventsets/sets/database.py +14 -14
  53. provide/foundation/eventsets/sets/http.py +21 -21
  54. provide/foundation/eventsets/sets/llm.py +16 -16
  55. provide/foundation/eventsets/sets/task_queue.py +13 -13
  56. provide/foundation/eventsets/types.py +7 -7
  57. provide/foundation/file/directory.py +14 -23
  58. provide/foundation/file/lock.py +4 -3
  59. provide/foundation/hub/components.py +75 -389
  60. provide/foundation/hub/config.py +157 -0
  61. provide/foundation/hub/discovery.py +63 -0
  62. provide/foundation/hub/handlers.py +89 -0
  63. provide/foundation/hub/lifecycle.py +195 -0
  64. provide/foundation/hub/manager.py +7 -4
  65. provide/foundation/hub/processors.py +49 -0
  66. provide/foundation/integrations/__init__.py +11 -0
  67. provide/foundation/{observability → integrations}/openobserve/__init__.py +10 -7
  68. provide/foundation/{observability → integrations}/openobserve/auth.py +1 -1
  69. provide/foundation/{observability → integrations}/openobserve/client.py +14 -14
  70. provide/foundation/{observability → integrations}/openobserve/commands.py +12 -12
  71. provide/foundation/integrations/openobserve/config.py +37 -0
  72. provide/foundation/{observability → integrations}/openobserve/formatters.py +1 -1
  73. provide/foundation/{observability → integrations}/openobserve/otlp.py +2 -2
  74. provide/foundation/{observability → integrations}/openobserve/search.py +2 -3
  75. provide/foundation/{observability → integrations}/openobserve/streaming.py +5 -5
  76. provide/foundation/logger/__init__.py +0 -1
  77. provide/foundation/logger/config/base.py +1 -1
  78. provide/foundation/logger/config/logging.py +69 -299
  79. provide/foundation/logger/config/telemetry.py +39 -121
  80. provide/foundation/logger/factories.py +2 -2
  81. provide/foundation/logger/processors/main.py +12 -10
  82. provide/foundation/logger/ratelimit/limiters.py +4 -4
  83. provide/foundation/logger/ratelimit/processor.py +1 -1
  84. provide/foundation/logger/setup/coordinator.py +39 -25
  85. provide/foundation/logger/setup/processors.py +3 -3
  86. provide/foundation/logger/setup/testing.py +14 -0
  87. provide/foundation/logger/trace.py +5 -5
  88. provide/foundation/metrics/__init__.py +1 -1
  89. provide/foundation/metrics/otel.py +3 -1
  90. provide/foundation/observability/__init__.py +3 -3
  91. provide/foundation/process/__init__.py +9 -0
  92. provide/foundation/process/exit.py +48 -0
  93. provide/foundation/process/lifecycle.py +69 -46
  94. provide/foundation/resilience/__init__.py +36 -0
  95. provide/foundation/resilience/circuit.py +166 -0
  96. provide/foundation/resilience/decorators.py +236 -0
  97. provide/foundation/resilience/fallback.py +208 -0
  98. provide/foundation/resilience/retry.py +327 -0
  99. provide/foundation/serialization/__init__.py +16 -0
  100. provide/foundation/serialization/core.py +70 -0
  101. provide/foundation/streams/config.py +78 -0
  102. provide/foundation/streams/console.py +4 -5
  103. provide/foundation/streams/core.py +5 -2
  104. provide/foundation/streams/file.py +12 -2
  105. provide/foundation/testing/__init__.py +29 -9
  106. provide/foundation/testing/archive/__init__.py +7 -7
  107. provide/foundation/testing/archive/fixtures.py +58 -54
  108. provide/foundation/testing/cli.py +30 -20
  109. provide/foundation/testing/common/__init__.py +13 -15
  110. provide/foundation/testing/common/fixtures.py +27 -57
  111. provide/foundation/testing/file/__init__.py +15 -15
  112. provide/foundation/testing/file/content_fixtures.py +289 -0
  113. provide/foundation/testing/file/directory_fixtures.py +107 -0
  114. provide/foundation/testing/file/fixtures.py +42 -516
  115. provide/foundation/testing/file/special_fixtures.py +145 -0
  116. provide/foundation/testing/logger.py +89 -8
  117. provide/foundation/testing/mocking/__init__.py +21 -21
  118. provide/foundation/testing/mocking/fixtures.py +80 -67
  119. provide/foundation/testing/process/__init__.py +23 -23
  120. provide/foundation/testing/process/async_fixtures.py +414 -0
  121. provide/foundation/testing/process/fixtures.py +48 -571
  122. provide/foundation/testing/process/subprocess_fixtures.py +210 -0
  123. provide/foundation/testing/threading/__init__.py +17 -17
  124. provide/foundation/testing/threading/basic_fixtures.py +105 -0
  125. provide/foundation/testing/threading/data_fixtures.py +101 -0
  126. provide/foundation/testing/threading/execution_fixtures.py +278 -0
  127. provide/foundation/testing/threading/fixtures.py +32 -502
  128. provide/foundation/testing/threading/sync_fixtures.py +100 -0
  129. provide/foundation/testing/time/__init__.py +11 -11
  130. provide/foundation/testing/time/fixtures.py +95 -83
  131. provide/foundation/testing/transport/__init__.py +9 -9
  132. provide/foundation/testing/transport/fixtures.py +54 -54
  133. provide/foundation/time/__init__.py +18 -0
  134. provide/foundation/time/core.py +63 -0
  135. provide/foundation/tools/__init__.py +2 -2
  136. provide/foundation/tools/base.py +68 -67
  137. provide/foundation/tools/cache.py +69 -74
  138. provide/foundation/tools/downloader.py +68 -62
  139. provide/foundation/tools/installer.py +51 -57
  140. provide/foundation/tools/registry.py +38 -45
  141. provide/foundation/tools/resolver.py +70 -68
  142. provide/foundation/tools/verifier.py +39 -50
  143. provide/foundation/tracer/spans.py +2 -14
  144. provide/foundation/transport/__init__.py +26 -33
  145. provide/foundation/transport/base.py +32 -30
  146. provide/foundation/transport/client.py +44 -49
  147. provide/foundation/transport/config.py +36 -107
  148. provide/foundation/transport/errors.py +13 -27
  149. provide/foundation/transport/http.py +69 -55
  150. provide/foundation/transport/middleware.py +113 -114
  151. provide/foundation/transport/registry.py +29 -27
  152. provide/foundation/transport/types.py +6 -6
  153. provide/foundation/utils/deps.py +17 -14
  154. provide/foundation/utils/parsing.py +49 -4
  155. {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/METADATA +2 -2
  156. provide_foundation-0.0.0.dev3.dist-info/RECORD +233 -0
  157. provide_foundation-0.0.0.dev1.dist-info/RECORD +0 -200
  158. /provide/foundation/{observability → integrations}/openobserve/exceptions.py +0 -0
  159. /provide/foundation/{observability → integrations}/openobserve/models.py +0 -0
  160. {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/WHEEL +0 -0
  161. {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/entry_points.txt +0 -0
  162. {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/licenses/LICENSE +0 -0
  163. {provide_foundation-0.0.0.dev1.dist-info → provide_foundation-0.0.0.dev3.dist-info}/top_level.txt +0 -0
@@ -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
- f"No download URL for {self.tool_name} {version}"
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}