provide-foundation 0.0.0.dev2__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 (155) hide show
  1. provide/foundation/__init__.py +20 -20
  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 +90 -91
  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 +4 -4
  13. provide/foundation/cli/commands/logs/__init__.py +2 -2
  14. provide/foundation/cli/commands/logs/generate.py +2 -2
  15. provide/foundation/cli/commands/logs/query.py +3 -3
  16. provide/foundation/cli/commands/logs/send.py +2 -2
  17. provide/foundation/cli/commands/logs/tail.py +2 -2
  18. provide/foundation/cli/decorators.py +0 -1
  19. provide/foundation/cli/testing.py +0 -5
  20. provide/foundation/cli/utils.py +1 -2
  21. provide/foundation/config/__init__.py +19 -19
  22. provide/foundation/config/base.py +2 -2
  23. provide/foundation/config/converters.py +81 -83
  24. provide/foundation/config/defaults.py +1 -1
  25. provide/foundation/config/env.py +2 -1
  26. provide/foundation/config/loader.py +1 -1
  27. provide/foundation/config/sync.py +8 -6
  28. provide/foundation/config/types.py +5 -5
  29. provide/foundation/config/validators.py +4 -4
  30. provide/foundation/console/output.py +7 -7
  31. provide/foundation/context/core.py +19 -17
  32. provide/foundation/crypto/certificates/__init__.py +9 -5
  33. provide/foundation/crypto/certificates/base.py +2 -2
  34. provide/foundation/crypto/certificates/certificate.py +48 -19
  35. provide/foundation/crypto/certificates/factory.py +26 -18
  36. provide/foundation/crypto/certificates/generator.py +24 -23
  37. provide/foundation/crypto/certificates/loader.py +24 -16
  38. provide/foundation/crypto/certificates/operations.py +17 -10
  39. provide/foundation/crypto/certificates/trust.py +21 -21
  40. provide/foundation/env/__init__.py +28 -0
  41. provide/foundation/env/core.py +218 -0
  42. provide/foundation/errors/__init__.py +3 -2
  43. provide/foundation/errors/decorators.py +0 -3
  44. provide/foundation/errors/types.py +0 -1
  45. provide/foundation/eventsets/display.py +13 -14
  46. provide/foundation/eventsets/registry.py +61 -31
  47. provide/foundation/eventsets/resolver.py +50 -46
  48. provide/foundation/eventsets/sets/das.py +8 -8
  49. provide/foundation/eventsets/sets/database.py +14 -14
  50. provide/foundation/eventsets/sets/http.py +21 -21
  51. provide/foundation/eventsets/sets/llm.py +16 -16
  52. provide/foundation/eventsets/sets/task_queue.py +13 -13
  53. provide/foundation/eventsets/types.py +7 -7
  54. provide/foundation/file/directory.py +1 -1
  55. provide/foundation/file/lock.py +2 -3
  56. provide/foundation/hub/components.py +19 -21
  57. provide/foundation/hub/config.py +25 -19
  58. provide/foundation/hub/discovery.py +5 -4
  59. provide/foundation/hub/handlers.py +13 -5
  60. provide/foundation/hub/lifecycle.py +10 -9
  61. provide/foundation/hub/manager.py +3 -0
  62. provide/foundation/hub/processors.py +8 -3
  63. provide/foundation/integrations/__init__.py +1 -1
  64. provide/foundation/integrations/openobserve/client.py +2 -2
  65. provide/foundation/integrations/openobserve/commands.py +9 -9
  66. provide/foundation/integrations/openobserve/config.py +2 -2
  67. provide/foundation/integrations/openobserve/otlp.py +2 -2
  68. provide/foundation/integrations/openobserve/search.py +1 -2
  69. provide/foundation/integrations/openobserve/streaming.py +1 -1
  70. provide/foundation/logger/__init__.py +0 -1
  71. provide/foundation/logger/config/base.py +1 -1
  72. provide/foundation/logger/config/logging.py +19 -19
  73. provide/foundation/logger/config/telemetry.py +11 -13
  74. provide/foundation/logger/factories.py +2 -2
  75. provide/foundation/logger/processors/main.py +12 -10
  76. provide/foundation/logger/ratelimit/limiters.py +4 -4
  77. provide/foundation/logger/ratelimit/processor.py +1 -1
  78. provide/foundation/logger/setup/coordinator.py +38 -24
  79. provide/foundation/logger/setup/processors.py +3 -3
  80. provide/foundation/logger/setup/testing.py +14 -0
  81. provide/foundation/logger/trace.py +5 -5
  82. provide/foundation/metrics/__init__.py +1 -1
  83. provide/foundation/metrics/otel.py +3 -1
  84. provide/foundation/observability/__init__.py +1 -1
  85. provide/foundation/process/__init__.py +1 -1
  86. provide/foundation/process/exit.py +6 -5
  87. provide/foundation/process/lifecycle.py +41 -18
  88. provide/foundation/resilience/__init__.py +6 -5
  89. provide/foundation/resilience/circuit.py +32 -30
  90. provide/foundation/resilience/decorators.py +58 -42
  91. provide/foundation/resilience/fallback.py +55 -40
  92. provide/foundation/resilience/retry.py +67 -65
  93. provide/foundation/serialization/__init__.py +16 -0
  94. provide/foundation/serialization/core.py +70 -0
  95. provide/foundation/streams/config.py +8 -9
  96. provide/foundation/streams/console.py +3 -3
  97. provide/foundation/streams/core.py +2 -2
  98. provide/foundation/streams/file.py +1 -1
  99. provide/foundation/testing/__init__.py +22 -7
  100. provide/foundation/testing/archive/__init__.py +7 -7
  101. provide/foundation/testing/archive/fixtures.py +58 -54
  102. provide/foundation/testing/cli.py +3 -6
  103. provide/foundation/testing/common/__init__.py +13 -13
  104. provide/foundation/testing/common/fixtures.py +27 -30
  105. provide/foundation/testing/file/__init__.py +15 -15
  106. provide/foundation/testing/file/content_fixtures.py +65 -92
  107. provide/foundation/testing/file/directory_fixtures.py +19 -19
  108. provide/foundation/testing/file/fixtures.py +14 -17
  109. provide/foundation/testing/file/special_fixtures.py +34 -42
  110. provide/foundation/testing/logger.py +28 -23
  111. provide/foundation/testing/mocking/__init__.py +21 -21
  112. provide/foundation/testing/mocking/fixtures.py +80 -67
  113. provide/foundation/testing/process/__init__.py +23 -23
  114. provide/foundation/testing/process/async_fixtures.py +89 -80
  115. provide/foundation/testing/process/fixtures.py +11 -13
  116. provide/foundation/testing/process/subprocess_fixtures.py +41 -40
  117. provide/foundation/testing/threading/__init__.py +17 -17
  118. provide/foundation/testing/threading/basic_fixtures.py +21 -17
  119. provide/foundation/testing/threading/data_fixtures.py +18 -16
  120. provide/foundation/testing/threading/execution_fixtures.py +67 -52
  121. provide/foundation/testing/threading/fixtures.py +10 -14
  122. provide/foundation/testing/threading/sync_fixtures.py +21 -18
  123. provide/foundation/testing/time/__init__.py +11 -11
  124. provide/foundation/testing/time/fixtures.py +91 -79
  125. provide/foundation/testing/transport/__init__.py +9 -9
  126. provide/foundation/testing/transport/fixtures.py +54 -54
  127. provide/foundation/time/__init__.py +18 -0
  128. provide/foundation/time/core.py +63 -0
  129. provide/foundation/tools/__init__.py +2 -2
  130. provide/foundation/tools/base.py +68 -67
  131. provide/foundation/tools/cache.py +62 -69
  132. provide/foundation/tools/downloader.py +51 -56
  133. provide/foundation/tools/installer.py +51 -57
  134. provide/foundation/tools/registry.py +38 -45
  135. provide/foundation/tools/resolver.py +70 -68
  136. provide/foundation/tools/verifier.py +39 -50
  137. provide/foundation/tracer/spans.py +1 -13
  138. provide/foundation/transport/__init__.py +26 -33
  139. provide/foundation/transport/base.py +32 -30
  140. provide/foundation/transport/client.py +44 -49
  141. provide/foundation/transport/config.py +11 -13
  142. provide/foundation/transport/errors.py +13 -27
  143. provide/foundation/transport/http.py +69 -55
  144. provide/foundation/transport/middleware.py +86 -81
  145. provide/foundation/transport/registry.py +29 -27
  146. provide/foundation/transport/types.py +6 -6
  147. provide/foundation/utils/deps.py +3 -2
  148. provide/foundation/utils/parsing.py +7 -7
  149. {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/METADATA +2 -2
  150. provide_foundation-0.0.0.dev3.dist-info/RECORD +233 -0
  151. provide_foundation-0.0.0.dev2.dist-info/RECORD +0 -225
  152. {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/WHEEL +0 -0
  153. {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/entry_points.txt +0 -0
  154. {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/licenses/LICENSE +0 -0
  155. {provide_foundation-0.0.0.dev2.dist-info → provide_foundation-0.0.0.dev3.dist-info}/top_level.txt +0 -0
@@ -24,13 +24,12 @@ except ImportError:
24
24
  _HAS_CRYPTO = False
25
25
 
26
26
  from provide.foundation import logger
27
- from provide.foundation.crypto.constants import (
28
- DEFAULT_CERTIFICATE_CURVE,
29
- DEFAULT_CERTIFICATE_KEY_TYPE,
30
- DEFAULT_CERTIFICATE_VALIDITY_DAYS,
31
- DEFAULT_RSA_KEY_SIZE,
27
+ from provide.foundation.crypto.certificates.base import (
28
+ CertificateBase,
29
+ CertificateError,
30
+ KeyPair,
31
+ PublicKey,
32
32
  )
33
- from provide.foundation.crypto.certificates.base import CertificateBase, CertificateError, KeyPair, PublicKey
34
33
 
35
34
 
36
35
  def create_x509_certificate(
@@ -46,8 +45,12 @@ def create_x509_certificate(
46
45
  try:
47
46
  logger.debug("📜📝🚀 create_x509_certificate: Building certificate")
48
47
 
49
- actual_issuer_name = issuer_name_override if issuer_name_override else base.issuer
50
- actual_signing_key = signing_key_override if signing_key_override else private_key
48
+ actual_issuer_name = (
49
+ issuer_name_override if issuer_name_override else base.issuer
50
+ )
51
+ actual_signing_key = (
52
+ signing_key_override if signing_key_override else private_key
53
+ )
51
54
 
52
55
  if not actual_signing_key:
53
56
  raise CertificateError(
@@ -147,7 +150,11 @@ def create_x509_certificate(
147
150
  raise CertificateError("Failed to create X.509 certificate object") from e
148
151
 
149
152
 
150
- def validate_signature(signed_cert_obj: "X509Certificate", signing_cert_obj: "X509Certificate", signing_public_key: "PublicKey") -> bool:
153
+ def validate_signature(
154
+ signed_cert_obj: "X509Certificate",
155
+ signing_cert_obj: "X509Certificate",
156
+ signing_public_key: "PublicKey",
157
+ ) -> bool:
151
158
  """Internal helper: Validates signature and issuer/subject match."""
152
159
  if signed_cert_obj.issuer != signing_cert_obj.subject:
153
160
  logger.debug(
@@ -195,4 +202,4 @@ def validate_signature(signed_cert_obj: "X509Certificate", signing_cert_obj: "X5
195
202
 
196
203
  except Exception as e:
197
204
  logger.debug(f"📜🔍❌ Signature validation failed: {type(e).__name__}: {e}")
198
- return False
205
+ return False
@@ -1,9 +1,14 @@
1
1
  """Certificate trust chain and verification utilities."""
2
2
 
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from provide.foundation.crypto.certificates.certificate import Certificate
7
+
3
8
  try:
4
9
  from cryptography import x509
5
10
  from cryptography.hazmat.primitives.asymmetric import ec, rsa
6
-
11
+
7
12
  _HAS_CRYPTO = True
8
13
  except ImportError:
9
14
  x509 = None
@@ -23,45 +28,41 @@ def verify_trust(
23
28
  ) -> bool:
24
29
  """
25
30
  Verifies if the other_cert is trusted based on this certificate's trust chain.
26
-
31
+
27
32
  Args:
28
33
  cert: The certificate doing the verification
29
34
  other_cert: The certificate to verify
30
35
  trust_chain: List of trusted certificates
31
-
36
+
32
37
  Returns:
33
38
  True if the certificate is trusted, False otherwise
34
39
  """
35
40
  if other_cert is None:
36
41
  raise CertificateError("Cannot verify trust: other_cert is None")
37
-
42
+
38
43
  logger.debug(
39
44
  f"📜🔍🚀 Verifying trust for cert S/N {other_cert.serial_number} "
40
45
  f"against chain of S/N {cert.serial_number}"
41
46
  )
42
-
47
+
43
48
  if not other_cert.is_valid:
44
- logger.debug(
45
- "📜🔍⚠️ Trust verification failed: Other certificate is not valid"
46
- )
49
+ logger.debug("📜🔍⚠️ Trust verification failed: Other certificate is not valid")
47
50
  return False
48
51
  if not other_cert.public_key:
49
52
  raise CertificateError(
50
53
  "Cannot verify trust: Other certificate has no public key"
51
54
  )
52
-
55
+
53
56
  if cert == other_cert:
54
57
  logger.debug(
55
58
  "📜🔍✅ Trust verified: Certificates are identical (based on subject/serial)"
56
59
  )
57
60
  return True
58
-
61
+
59
62
  if other_cert in trust_chain:
60
- logger.debug(
61
- "📜🔍✅ Trust verified: Other certificate found in trust chain"
62
- )
63
+ logger.debug("📜🔍✅ Trust verified: Other certificate found in trust chain")
63
64
  return True
64
-
65
+
65
66
  for trusted_cert in trust_chain:
66
67
  logger.debug(
67
68
  f"📜🔍🔁 Checking signature against trusted cert S/N {trusted_cert.serial_number}"
@@ -74,7 +75,7 @@ def verify_trust(
74
75
  f"{trusted_cert.serial_number}"
75
76
  )
76
77
  return True
77
-
78
+
78
79
  logger.debug(
79
80
  "📜🔍❌ Trust verification failed: Other certificate not identical, "
80
81
  "not in chain, and not signed by any cert in chain"
@@ -83,16 +84,15 @@ def verify_trust(
83
84
 
84
85
 
85
86
  def validate_signature_wrapper(
86
- signed_cert: "Certificate",
87
- signing_cert: "Certificate"
87
+ signed_cert: "Certificate", signing_cert: "Certificate"
88
88
  ) -> bool:
89
89
  """
90
90
  Internal helper: Validates signature and issuer/subject match.
91
-
91
+
92
92
  Args:
93
93
  signed_cert: The certificate that was signed
94
94
  signing_cert: The certificate that did the signing
95
-
95
+
96
96
  Returns:
97
97
  True if signature is valid, False otherwise
98
98
  """
@@ -101,7 +101,7 @@ def validate_signature_wrapper(
101
101
  "📜🔍❌ Cannot validate signature: Certificate object(s) not initialized"
102
102
  )
103
103
  return False
104
-
104
+
105
105
  return validate_signature(
106
106
  signed_cert._cert, signing_cert._cert, signing_cert.public_key
107
- )
107
+ )
@@ -0,0 +1,28 @@
1
+ """
2
+ Environment variable access utilities for Foundation.
3
+
4
+ Provides consistent environment variable handling with validation,
5
+ testing support, and integration with Foundation's configuration system.
6
+ """
7
+
8
+ from provide.foundation.env.core import (
9
+ get_env,
10
+ get_env_bool,
11
+ get_env_float,
12
+ get_env_int,
13
+ get_env_list,
14
+ has_env,
15
+ set_env,
16
+ unset_env,
17
+ )
18
+
19
+ __all__ = [
20
+ "get_env",
21
+ "get_env_bool",
22
+ "get_env_float",
23
+ "get_env_int",
24
+ "get_env_list",
25
+ "has_env",
26
+ "set_env",
27
+ "unset_env",
28
+ ]
@@ -0,0 +1,218 @@
1
+ """Core environment variable utilities for Foundation."""
2
+
3
+ import os
4
+
5
+ from provide.foundation.errors import ValidationError
6
+
7
+
8
+ def get_env(key: str, default: str | None = None) -> str | None:
9
+ """
10
+ Get environment variable with Foundation tracking.
11
+
12
+ Args:
13
+ key: Environment variable name
14
+ default: Default value if variable not found
15
+
16
+ Returns:
17
+ Environment variable value or default
18
+
19
+ Example:
20
+ >>> get_env("HOME") # doctest: +SKIP
21
+ '/Users/username'
22
+ >>> get_env("NONEXISTENT", "fallback")
23
+ 'fallback'
24
+ """
25
+ return os.environ.get(key, default)
26
+
27
+
28
+ def set_env(key: str, value: str) -> None:
29
+ """
30
+ Set environment variable with validation.
31
+
32
+ Args:
33
+ key: Environment variable name
34
+ value: Value to set
35
+
36
+ Raises:
37
+ ValidationError: If key or value is invalid
38
+
39
+ Example:
40
+ >>> set_env("TEST_VAR", "test_value")
41
+ >>> get_env("TEST_VAR")
42
+ 'test_value'
43
+ """
44
+ if not isinstance(key, str) or not key:
45
+ raise ValidationError("Environment variable key must be a non-empty string")
46
+ if not isinstance(value, str):
47
+ raise ValidationError("Environment variable value must be a string")
48
+
49
+ os.environ[key] = value
50
+
51
+
52
+ def unset_env(key: str) -> None:
53
+ """
54
+ Remove environment variable if it exists.
55
+
56
+ Args:
57
+ key: Environment variable name to remove
58
+
59
+ Example:
60
+ >>> set_env("TEMP_VAR", "value")
61
+ >>> unset_env("TEMP_VAR")
62
+ >>> has_env("TEMP_VAR")
63
+ False
64
+ """
65
+ os.environ.pop(key, None)
66
+
67
+
68
+ def has_env(key: str) -> bool:
69
+ """
70
+ Check if environment variable exists.
71
+
72
+ Args:
73
+ key: Environment variable name
74
+
75
+ Returns:
76
+ True if variable exists, False otherwise
77
+
78
+ Example:
79
+ >>> has_env("PATH")
80
+ True
81
+ >>> has_env("DEFINITELY_NOT_SET")
82
+ False
83
+ """
84
+ return key in os.environ
85
+
86
+
87
+ def get_env_int(key: str, default: int | None = None) -> int | None:
88
+ """
89
+ Get environment variable as integer.
90
+
91
+ Args:
92
+ key: Environment variable name
93
+ default: Default value if variable not found or invalid
94
+
95
+ Returns:
96
+ Integer value or default
97
+
98
+ Raises:
99
+ ValidationError: If value exists but cannot be converted to int
100
+
101
+ Example:
102
+ >>> set_env("PORT", "8080")
103
+ >>> get_env_int("PORT")
104
+ 8080
105
+ >>> get_env_int("MISSING_PORT", 3000)
106
+ 3000
107
+ """
108
+ value = os.environ.get(key)
109
+ if value is None:
110
+ return default
111
+
112
+ try:
113
+ return int(value)
114
+ except ValueError as e:
115
+ raise ValidationError(
116
+ f"Environment variable {key}='{value}' cannot be converted to int"
117
+ ) from e
118
+
119
+
120
+ def get_env_bool(key: str, default: bool | None = None) -> bool | None:
121
+ """
122
+ Get environment variable as boolean.
123
+
124
+ Recognizes: true/false, yes/no, 1/0, on/off (case insensitive)
125
+
126
+ Args:
127
+ key: Environment variable name
128
+ default: Default value if variable not found
129
+
130
+ Returns:
131
+ Boolean value or default
132
+
133
+ Raises:
134
+ ValidationError: If value exists but cannot be converted to bool
135
+
136
+ Example:
137
+ >>> set_env("DEBUG", "true")
138
+ >>> get_env_bool("DEBUG")
139
+ True
140
+ >>> set_env("VERBOSE", "no")
141
+ >>> get_env_bool("VERBOSE")
142
+ False
143
+ """
144
+ value = os.environ.get(key)
145
+ if value is None:
146
+ return default
147
+
148
+ value_lower = value.lower().strip()
149
+ if value_lower in ("true", "yes", "1", "on"):
150
+ return True
151
+ elif value_lower in ("false", "no", "0", "off"):
152
+ return False
153
+ else:
154
+ raise ValidationError(
155
+ f"Environment variable {key}='{value}' cannot be converted to bool"
156
+ )
157
+
158
+
159
+ def get_env_float(key: str, default: float | None = None) -> float | None:
160
+ """
161
+ Get environment variable as float.
162
+
163
+ Args:
164
+ key: Environment variable name
165
+ default: Default value if variable not found or invalid
166
+
167
+ Returns:
168
+ Float value or default
169
+
170
+ Raises:
171
+ ValidationError: If value exists but cannot be converted to float
172
+
173
+ Example:
174
+ >>> set_env("TIMEOUT", "30.5")
175
+ >>> get_env_float("TIMEOUT")
176
+ 30.5
177
+ """
178
+ value = os.environ.get(key)
179
+ if value is None:
180
+ return default
181
+
182
+ try:
183
+ return float(value)
184
+ except ValueError as e:
185
+ raise ValidationError(
186
+ f"Environment variable {key}='{value}' cannot be converted to float"
187
+ ) from e
188
+
189
+
190
+ def get_env_list(
191
+ key: str, separator: str = ",", default: list[str] | None = None
192
+ ) -> list[str] | None:
193
+ """
194
+ Get environment variable as list of strings.
195
+
196
+ Args:
197
+ key: Environment variable name
198
+ separator: Character to split on (default: comma)
199
+ default: Default value if variable not found
200
+
201
+ Returns:
202
+ List of strings or default
203
+
204
+ Example:
205
+ >>> set_env("ALLOWED_HOSTS", "localhost,127.0.0.1,example.com")
206
+ >>> get_env_list("ALLOWED_HOSTS")
207
+ ['localhost', '127.0.0.1', 'example.com']
208
+ >>> get_env_list("MISSING", default=["fallback"])
209
+ ['fallback']
210
+ """
211
+ value = os.environ.get(key)
212
+ if value is None:
213
+ return default
214
+
215
+ if not value.strip():
216
+ return []
217
+
218
+ return [item.strip() for item in value.split(separator) if item.strip()]
@@ -6,8 +6,6 @@ and utilities for robust error handling throughout the application.
6
6
  """
7
7
 
8
8
  from provide.foundation.errors.auth import AuthenticationError, AuthorizationError
9
- # Re-export from resilience module for compatibility
10
- from provide.foundation.resilience.decorators import retry as retry_on_error
11
9
  from provide.foundation.errors.base import FoundationError
12
10
  from provide.foundation.errors.config import (
13
11
  ConfigurationError,
@@ -53,6 +51,9 @@ from provide.foundation.errors.types import (
53
51
  ErrorMetadata,
54
52
  )
55
53
 
54
+ # Re-export from resilience module for compatibility
55
+ from provide.foundation.resilience.decorators import retry as retry_on_error
56
+
56
57
  __all__ = [
57
58
  "AlreadyExistsError",
58
59
  "AuthenticationError",
@@ -144,7 +144,6 @@ def with_error_handling(
144
144
  return decorator(func)
145
145
 
146
146
 
147
-
148
147
  def suppress_and_log(
149
148
  *exceptions: type[Exception],
150
149
  fallback: Any = None,
@@ -249,5 +248,3 @@ def fallback_on_error(
249
248
  return wrapper # type: ignore
250
249
 
251
250
  return decorator
252
-
253
-
@@ -118,7 +118,6 @@ class ErrorMetadata:
118
118
  return result
119
119
 
120
120
 
121
-
122
121
  @define(kw_only=True, slots=True)
123
122
  class ErrorResponse:
124
123
  """Structured error response for APIs and external interfaces.
@@ -2,10 +2,9 @@
2
2
  Event set display utilities for Foundation.
3
3
  """
4
4
 
5
- from provide.foundation.logger import get_logger
6
-
7
- from provide.foundation.eventsets.registry import get_registry, discover_event_sets
5
+ from provide.foundation.eventsets.registry import discover_event_sets, get_registry
8
6
  from provide.foundation.eventsets.resolver import get_resolver
7
+ from provide.foundation.logger import get_logger
9
8
 
10
9
  logger = get_logger(__name__)
11
10
 
@@ -17,16 +16,16 @@ def show_event_matrix() -> None:
17
16
  """
18
17
  # Ensure event sets are discovered
19
18
  discover_event_sets()
20
-
19
+
21
20
  registry = get_registry()
22
21
  resolver = get_resolver()
23
-
22
+
24
23
  # Force resolution to ensure everything is loaded
25
24
  resolver.resolve()
26
-
25
+
27
26
  lines: list[str] = ["Foundation Event Sets: Active Configuration"]
28
27
  lines.append("=" * 70)
29
-
28
+
30
29
  # Show registered event sets
31
30
  event_sets = registry.list_event_sets()
32
31
  if event_sets:
@@ -35,7 +34,7 @@ def show_event_matrix() -> None:
35
34
  lines.append(f"\n {config.name} (priority: {config.priority})")
36
35
  if config.description:
37
36
  lines.append(f" {config.description}")
38
-
37
+
39
38
  # Show field mappings
40
39
  if config.field_mappings:
41
40
  lines.append(f" Field Mappings ({len(config.field_mappings)}):")
@@ -43,7 +42,7 @@ def show_event_matrix() -> None:
43
42
  lines.append(f" - {mapping.log_key}")
44
43
  if len(config.field_mappings) > 5:
45
44
  lines.append(f" ... and {len(config.field_mappings) - 5} more")
46
-
45
+
47
46
  # Show event sets
48
47
  if config.event_sets:
49
48
  lines.append(f" Event Sets ({len(config.event_sets)}):")
@@ -59,15 +58,15 @@ def show_event_matrix() -> None:
59
58
  )
60
59
  else:
61
60
  lines.append("\n (No event sets registered)")
62
-
61
+
63
62
  lines.append("\n" + "=" * 70)
64
-
63
+
65
64
  # Show resolved state
66
65
  if resolver._resolved:
67
66
  lines.append("\nResolver State:")
68
67
  lines.append(f" Total Field Mappings: {len(resolver._field_mappings)}")
69
68
  lines.append(f" Total Event Sets: {len(resolver._event_sets)}")
70
-
69
+
71
70
  # Show sample visual markers
72
71
  if resolver._event_sets:
73
72
  lines.append("\n Sample Visual Markers:")
@@ -79,6 +78,6 @@ def show_event_matrix() -> None:
79
78
  lines.append(f" {marker} -> {key}")
80
79
  else:
81
80
  lines.append("\n (Resolver not yet initialized)")
82
-
81
+
83
82
  # Log the complete display
84
- logger.info("\n".join(lines))
83
+ logger.info("\n".join(lines))