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
@@ -20,7 +20,7 @@ EVENT_SET = EventSet(
20
20
  "options": "⚙️❔",
21
21
  "default": "🌐",
22
22
  },
23
- default_key="default"
23
+ default_key="default",
24
24
  ),
25
25
  EventMapping(
26
26
  name="http_status_class",
@@ -37,7 +37,7 @@ EVENT_SET = EventSet(
37
37
  "4xx": {"http.client_error": True},
38
38
  "5xx": {"http.server_error": True},
39
39
  },
40
- default_key="default"
40
+ default_key="default",
41
41
  ),
42
42
  EventMapping(
43
43
  name="http_target_type",
@@ -47,7 +47,7 @@ EVENT_SET = EventSet(
47
47
  "fragment": "#️⃣",
48
48
  "default": "🎯",
49
49
  },
50
- default_key="default"
50
+ default_key="default",
51
51
  ),
52
52
  ],
53
53
  field_mappings=[
@@ -55,99 +55,99 @@ EVENT_SET = EventSet(
55
55
  log_key="http.method",
56
56
  event_set_name="http",
57
57
  description="HTTP request method",
58
- value_type="string"
58
+ value_type="string",
59
59
  ),
60
60
  FieldMapping(
61
61
  log_key="http.status_class",
62
62
  event_set_name="http",
63
63
  description="HTTP status code class",
64
- value_type="string"
64
+ value_type="string",
65
65
  ),
66
66
  FieldMapping(
67
67
  log_key="http.target",
68
68
  event_set_name="http",
69
69
  description="Request target path and query",
70
70
  value_type="string",
71
- default_override_key="path"
71
+ default_override_key="path",
72
72
  ),
73
73
  FieldMapping(
74
74
  log_key="http.url",
75
75
  event_set_name="http",
76
76
  description="Full HTTP URL",
77
- value_type="string"
77
+ value_type="string",
78
78
  ),
79
79
  FieldMapping(
80
80
  log_key="http.scheme",
81
81
  event_set_name="http",
82
82
  description="URL scheme",
83
- value_type="string"
83
+ value_type="string",
84
84
  ),
85
85
  FieldMapping(
86
86
  log_key="http.host",
87
87
  event_set_name="http",
88
88
  description="Request hostname",
89
- value_type="string"
89
+ value_type="string",
90
90
  ),
91
91
  FieldMapping(
92
92
  log_key="http.status_code",
93
93
  event_set_name="http",
94
94
  description="HTTP response status code",
95
- value_type="integer"
95
+ value_type="integer",
96
96
  ),
97
97
  FieldMapping(
98
98
  log_key="http.request.body.size",
99
99
  event_set_name="http",
100
100
  description="Request body size in bytes",
101
- value_type="integer"
101
+ value_type="integer",
102
102
  ),
103
103
  FieldMapping(
104
104
  log_key="http.response.body.size",
105
105
  event_set_name="http",
106
106
  description="Response body size in bytes",
107
- value_type="integer"
107
+ value_type="integer",
108
108
  ),
109
109
  FieldMapping(
110
110
  log_key="client.address",
111
111
  event_set_name="http",
112
112
  description="Client IP address",
113
- value_type="string"
113
+ value_type="string",
114
114
  ),
115
115
  FieldMapping(
116
116
  log_key="server.address",
117
117
  event_set_name="http",
118
118
  description="Server address or hostname",
119
- value_type="string"
119
+ value_type="string",
120
120
  ),
121
121
  FieldMapping(
122
122
  log_key="duration_ms",
123
123
  event_set_name="http",
124
124
  description="Request duration in milliseconds",
125
- value_type="integer"
125
+ value_type="integer",
126
126
  ),
127
127
  FieldMapping(
128
128
  log_key="trace_id",
129
129
  event_set_name="http",
130
130
  description="Distributed trace ID",
131
- value_type="string"
131
+ value_type="string",
132
132
  ),
133
133
  FieldMapping(
134
134
  log_key="span_id",
135
135
  event_set_name="http",
136
136
  description="Span ID",
137
- value_type="string"
137
+ value_type="string",
138
138
  ),
139
139
  FieldMapping(
140
140
  log_key="error.message",
141
141
  event_set_name="http",
142
142
  description="Error message if request failed",
143
- value_type="string"
143
+ value_type="string",
144
144
  ),
145
145
  FieldMapping(
146
146
  log_key="error.type",
147
147
  event_set_name="http",
148
148
  description="Error type if request failed",
149
- value_type="string"
149
+ value_type="string",
150
150
  ),
151
151
  ],
152
- priority=80
153
- )
152
+ priority=80,
153
+ )
@@ -2,7 +2,7 @@
2
2
  Large Language Model (LLM) interaction event set for Foundation.
3
3
  """
4
4
 
5
- from provide.foundation.eventsets.types import EventSet, EventMapping, FieldMapping
5
+ from provide.foundation.eventsets.types import EventMapping, EventSet, FieldMapping
6
6
 
7
7
  EVENT_SET = EventSet(
8
8
  name="llm",
@@ -27,7 +27,7 @@ EVENT_SET = EventSet(
27
27
  "meta": {"llm.vendor": "meta", "llm.api": "llama"},
28
28
  "mistral": {"llm.vendor": "mistral", "llm.api": "mistral"},
29
29
  },
30
- default_key="default"
30
+ default_key="default",
31
31
  ),
32
32
  EventMapping(
33
33
  name="llm_task",
@@ -49,7 +49,7 @@ EVENT_SET = EventSet(
49
49
  "chat": {"llm.type": "conversational"},
50
50
  "tool_use": {"llm.type": "function_calling"},
51
51
  },
52
- default_key="default"
52
+ default_key="default",
53
53
  ),
54
54
  EventMapping(
55
55
  name="llm_outcome",
@@ -70,7 +70,7 @@ EVENT_SET = EventSet(
70
70
  "filtered_input": {"llm.filtered": True, "llm.filter_type": "input"},
71
71
  "filtered_output": {"llm.filtered": True, "llm.filter_type": "output"},
72
72
  },
73
- default_key="default"
73
+ default_key="default",
74
74
  ),
75
75
  ],
76
76
  field_mappings=[
@@ -78,62 +78,62 @@ EVENT_SET = EventSet(
78
78
  log_key="llm.provider",
79
79
  event_set_name="llm",
80
80
  description="LLM provider name",
81
- value_type="string"
81
+ value_type="string",
82
82
  ),
83
83
  FieldMapping(
84
84
  log_key="llm.task",
85
85
  event_set_name="llm",
86
86
  description="LLM task type",
87
- value_type="string"
87
+ value_type="string",
88
88
  ),
89
89
  FieldMapping(
90
90
  log_key="llm.model",
91
91
  event_set_name="llm",
92
92
  description="Model identifier",
93
- value_type="string"
93
+ value_type="string",
94
94
  ),
95
95
  FieldMapping(
96
96
  log_key="llm.outcome",
97
97
  event_set_name="llm",
98
98
  description="Operation outcome",
99
- value_type="string"
99
+ value_type="string",
100
100
  ),
101
101
  FieldMapping(
102
102
  log_key="llm.input.tokens",
103
103
  event_set_name="llm",
104
104
  description="Input token count",
105
- value_type="integer"
105
+ value_type="integer",
106
106
  ),
107
107
  FieldMapping(
108
108
  log_key="llm.output.tokens",
109
109
  event_set_name="llm",
110
110
  description="Output token count",
111
- value_type="integer"
111
+ value_type="integer",
112
112
  ),
113
113
  FieldMapping(
114
114
  log_key="llm.tool.name",
115
115
  event_set_name="llm",
116
116
  description="Tool/function name",
117
- value_type="string"
117
+ value_type="string",
118
118
  ),
119
119
  FieldMapping(
120
120
  log_key="llm.tool.call_id",
121
121
  event_set_name="llm",
122
122
  description="Tool call identifier",
123
- value_type="string"
123
+ value_type="string",
124
124
  ),
125
125
  FieldMapping(
126
126
  log_key="duration_ms",
127
127
  event_set_name="llm",
128
128
  description="LLM operation duration",
129
- value_type="integer"
129
+ value_type="integer",
130
130
  ),
131
131
  FieldMapping(
132
132
  log_key="trace_id",
133
133
  event_set_name="llm",
134
134
  description="Distributed trace ID",
135
- value_type="string"
135
+ value_type="string",
136
136
  ),
137
137
  ],
138
- priority=100 # High priority for LLM operations
139
- )
138
+ priority=100, # High priority for LLM operations
139
+ )
@@ -2,7 +2,7 @@
2
2
  Task queue and async job processing event set for Foundation.
3
3
  """
4
4
 
5
- from provide.foundation.eventsets.types import EventSet, EventMapping, FieldMapping
5
+ from provide.foundation.eventsets.types import EventMapping, EventSet, FieldMapping
6
6
 
7
7
  EVENT_SET = EventSet(
8
8
  name="task_queue",
@@ -25,7 +25,7 @@ EVENT_SET = EventSet(
25
25
  "kafka": {"task.broker": "kafka", "task.streaming": True},
26
26
  "rabbitmq": {"task.broker": "amqp"},
27
27
  },
28
- default_key="default"
28
+ default_key="default",
29
29
  ),
30
30
  EventMapping(
31
31
  name="task_status",
@@ -50,7 +50,7 @@ EVENT_SET = EventSet(
50
50
  "failure": {"task.state": "failed", "task.success": False},
51
51
  "revoked": {"task.state": "cancelled"},
52
52
  },
53
- default_key="default"
53
+ default_key="default",
54
54
  ),
55
55
  ],
56
56
  field_mappings=[
@@ -58,50 +58,50 @@ EVENT_SET = EventSet(
58
58
  log_key="task.system",
59
59
  event_set_name="task_queue",
60
60
  description="Task queue system",
61
- value_type="string"
61
+ value_type="string",
62
62
  ),
63
63
  FieldMapping(
64
64
  log_key="task.status",
65
65
  event_set_name="task_queue",
66
66
  description="Task execution status",
67
- value_type="string"
67
+ value_type="string",
68
68
  ),
69
69
  FieldMapping(
70
70
  log_key="task.id",
71
71
  event_set_name="task_queue",
72
72
  description="Unique task identifier",
73
- value_type="string"
73
+ value_type="string",
74
74
  ),
75
75
  FieldMapping(
76
76
  log_key="task.name",
77
77
  event_set_name="task_queue",
78
78
  description="Task or job name",
79
- value_type="string"
79
+ value_type="string",
80
80
  ),
81
81
  FieldMapping(
82
82
  log_key="task.queue_name",
83
83
  event_set_name="task_queue",
84
84
  description="Queue name",
85
- value_type="string"
85
+ value_type="string",
86
86
  ),
87
87
  FieldMapping(
88
88
  log_key="task.retries",
89
89
  event_set_name="task_queue",
90
90
  description="Retry attempt count",
91
- value_type="integer"
91
+ value_type="integer",
92
92
  ),
93
93
  FieldMapping(
94
94
  log_key="duration_ms",
95
95
  event_set_name="task_queue",
96
96
  description="Task execution duration",
97
- value_type="integer"
97
+ value_type="integer",
98
98
  ),
99
99
  FieldMapping(
100
100
  log_key="trace_id",
101
101
  event_set_name="task_queue",
102
102
  description="Distributed trace ID",
103
- value_type="string"
103
+ value_type="string",
104
104
  ),
105
105
  ],
106
- priority=70
107
- )
106
+ priority=70,
107
+ )
@@ -12,7 +12,7 @@ from attrs import define, field
12
12
  class EventMapping:
13
13
  """
14
14
  Individual event enrichment mapping for a specific domain.
15
-
15
+
16
16
  Attributes:
17
17
  name: Unique identifier for this mapping
18
18
  visual_markers: Mapping of values to visual indicators (e.g., emojis)
@@ -20,7 +20,7 @@ class EventMapping:
20
20
  transformations: Value transformation functions
21
21
  default_key: Key to use when no specific match is found
22
22
  """
23
-
23
+
24
24
  name: str
25
25
  visual_markers: dict[str, str] = field(factory=lambda: {})
26
26
  metadata_fields: dict[str, dict[str, Any]] = field(factory=lambda: {})
@@ -32,7 +32,7 @@ class EventMapping:
32
32
  class FieldMapping:
33
33
  """
34
34
  Maps a log field to an event set for enrichment.
35
-
35
+
36
36
  Attributes:
37
37
  log_key: The field key in log events (e.g., "http.method", "llm.provider")
38
38
  description: Human-readable description of this field
@@ -41,7 +41,7 @@ class FieldMapping:
41
41
  default_override_key: Override the default key for this specific field
42
42
  default_value: Default value to use if field is not present
43
43
  """
44
-
44
+
45
45
  log_key: str
46
46
  description: str | None = field(default=None)
47
47
  value_type: str | None = field(default=None)
@@ -54,7 +54,7 @@ class FieldMapping:
54
54
  class EventSet:
55
55
  """
56
56
  Complete event enrichment domain definition.
57
-
57
+
58
58
  Attributes:
59
59
  name: Unique identifier for this event set
60
60
  description: Human-readable description
@@ -62,9 +62,9 @@ class EventSet:
62
62
  field_mappings: List of field-to-mapping associations
63
63
  priority: Higher priority sets override lower ones
64
64
  """
65
-
65
+
66
66
  name: str
67
67
  description: str | None = field(default=None)
68
68
  mappings: list[EventMapping] = field(factory=lambda: [])
69
69
  field_mappings: list[FieldMapping] = field(factory=lambda: [])
70
- priority: int = field(default=0, converter=int)
70
+ priority: int = field(default=0, converter=int)
@@ -1,10 +1,10 @@
1
1
  """Directory operations and utilities."""
2
2
 
3
3
  from contextlib import contextmanager
4
- from typing import Generator
5
4
  from pathlib import Path
6
5
  import shutil
7
6
  import tempfile
7
+ from typing import Generator
8
8
 
9
9
  from provide.foundation.errors.decorators import with_error_handling
10
10
  from provide.foundation.errors.handlers import error_boundary
@@ -5,7 +5,6 @@ from pathlib import Path
5
5
  import time
6
6
 
7
7
  from provide.foundation.config.defaults import DEFAULT_FILE_LOCK_TIMEOUT
8
- from provide.foundation.errors.decorators import with_error_handling
9
8
  from provide.foundation.errors.resources import LockError
10
9
  from provide.foundation.logger import get_logger
11
10
 
@@ -160,12 +159,12 @@ class FileLock:
160
159
 
161
160
  return False
162
161
 
163
- def __enter__(self):
162
+ def __enter__(self) -> "FileLock":
164
163
  """Context manager entry."""
165
164
  self.acquire()
166
165
  return self
167
166
 
168
- def __exit__(self, exc_type, exc_val, exc_tb):
167
+ def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> bool:
169
168
  """Context manager exit."""
170
169
  self.release()
171
170
  return False # Don't suppress exceptions
@@ -6,8 +6,8 @@ components are managed through the Hub registry system. Provides centralized
6
6
  component discovery, lifecycle management, and dependency resolution.
7
7
  """
8
8
 
9
- import threading
10
9
  from enum import Enum
10
+ import threading
11
11
  from typing import Any, Protocol
12
12
 
13
13
  from attrs import define, field
@@ -73,7 +73,10 @@ def get_component_registry() -> Registry:
73
73
 
74
74
  @with_error_handling(
75
75
  fallback={"status": "error"},
76
- context_provider=lambda: {"function": "check_component_health", "module": "hub.components"}
76
+ context_provider=lambda: {
77
+ "function": "check_component_health",
78
+ "module": "hub.components",
79
+ },
77
80
  )
78
81
  def check_component_health(name: str, dimension: str) -> dict[str, Any]:
79
82
  """Check component health status."""
@@ -112,7 +115,7 @@ def bootstrap_foundation() -> None:
112
115
  registry = get_component_registry()
113
116
 
114
117
  # Register core processors
115
- def timestamp_processor(logger, method_name, event_dict):
118
+ def timestamp_processor(logger: object, method_name: str, event_dict: dict[str, Any]) -> dict[str, Any]:
116
119
  import time
117
120
 
118
121
  event_dict["timestamp"] = time.time()
@@ -138,43 +141,38 @@ def reset_registry_for_tests() -> None:
138
141
 
139
142
  # Import and re-export functions from specialized modules
140
143
  from provide.foundation.hub.config import (
141
- resolve_config_value,
142
144
  get_config_chain,
143
145
  load_all_configs,
144
146
  load_config_from_registry,
147
+ resolve_config_value,
148
+ )
149
+ from provide.foundation.hub.discovery import (
150
+ discover_components,
151
+ resolve_component_dependencies,
145
152
  )
146
-
147
153
  from provide.foundation.hub.handlers import (
148
- get_handlers_for_exception,
149
154
  execute_error_handlers,
155
+ get_handlers_for_exception,
150
156
  )
151
-
152
157
  from provide.foundation.hub.lifecycle import (
153
- get_or_initialize_component,
154
- initialize_async_component,
155
158
  cleanup_all_components,
159
+ get_or_initialize_component,
156
160
  initialize_all_async_components,
161
+ initialize_async_component,
157
162
  )
158
-
159
163
  from provide.foundation.hub.processors import (
160
164
  get_processor_pipeline,
161
165
  get_processors_for_stage,
162
166
  )
163
167
 
164
- from provide.foundation.hub.discovery import (
165
- resolve_component_dependencies,
166
- discover_components,
167
- )
168
-
169
-
170
- # Bootstrap on module import
171
- bootstrap_foundation()
168
+ # Bootstrap will happen lazily on first hub access to avoid circular imports
169
+ # bootstrap_foundation()
172
170
 
173
171
 
174
172
  __all__ = [
175
173
  # Core classes
176
174
  "ComponentInfo",
177
- "ComponentCategory",
175
+ "ComponentCategory",
178
176
  "ComponentLifecycle",
179
177
  # Registry access
180
178
  "get_component_registry",
@@ -189,7 +187,7 @@ __all__ = [
189
187
  "get_config_chain",
190
188
  "load_all_configs",
191
189
  "load_config_from_registry",
192
- "get_handlers_for_exception",
190
+ "get_handlers_for_exception",
193
191
  "execute_error_handlers",
194
192
  "get_or_initialize_component",
195
193
  "initialize_async_component",
@@ -199,4 +197,4 @@ __all__ = [
199
197
  "get_processors_for_stage",
200
198
  "resolve_component_dependencies",
201
199
  "discover_components",
202
- ]
200
+ ]
@@ -5,7 +5,6 @@ Provides functions for resolving configuration values from registered sources,
5
5
  loading configurations, and managing the configuration chain.
6
6
  """
7
7
 
8
- import asyncio
9
8
  import inspect
10
9
  from typing import Any, TypeVar
11
10
 
@@ -20,7 +19,12 @@ log = get_logger(__name__)
20
19
 
21
20
  def _get_registry_and_lock():
22
21
  """Get registry and lock from components module."""
23
- from provide.foundation.hub.components import get_component_registry, _registry_lock, ComponentCategory
22
+ from provide.foundation.hub.components import (
23
+ ComponentCategory,
24
+ _registry_lock,
25
+ get_component_registry,
26
+ )
27
+
24
28
  return get_component_registry(), _registry_lock, ComponentCategory
25
29
 
26
30
 
@@ -28,7 +32,7 @@ def _get_registry_and_lock():
28
32
  def resolve_config_value(key: str) -> Any:
29
33
  """Resolve configuration value using priority-ordered sources."""
30
34
  registry, registry_lock, ComponentCategory = _get_registry_and_lock()
31
-
35
+
32
36
  with registry_lock:
33
37
  # Get all config sources
34
38
  all_entries = list(registry)
@@ -59,7 +63,7 @@ def resolve_config_value(key: str) -> Any:
59
63
  def get_config_chain() -> list[RegistryEntry]:
60
64
  """Get configuration sources ordered by priority."""
61
65
  registry, registry_lock, ComponentCategory = _get_registry_and_lock()
62
-
66
+
63
67
  with registry_lock:
64
68
  # Get all config sources
65
69
  all_entries = list(registry)
@@ -75,8 +79,7 @@ def get_config_chain() -> list[RegistryEntry]:
75
79
 
76
80
 
77
81
  @with_error_handling(
78
- fallback={},
79
- context_provider=lambda: {"function": "load_all_configs"}
82
+ fallback={}, context_provider=lambda: {"function": "load_all_configs"}
80
83
  )
81
84
  async def load_all_configs() -> dict[str, Any]:
82
85
  """Load configurations from all registered sources."""
@@ -105,19 +108,19 @@ async def load_all_configs() -> dict[str, Any]:
105
108
  def load_config_from_registry(config_class: type[T]) -> T:
106
109
  """
107
110
  Load configuration from registry sources.
108
-
111
+
109
112
  Args:
110
113
  config_class: Configuration class to instantiate
111
-
114
+
112
115
  Returns:
113
116
  Configuration instance loaded from registry sources
114
117
  """
115
118
  registry, registry_lock, ComponentCategory = _get_registry_and_lock()
116
-
119
+
117
120
  with registry_lock:
118
121
  # Get configuration data from registry
119
122
  config_data = {}
120
-
123
+
121
124
  # Load from all config sources
122
125
  chain = get_config_chain()
123
126
  for entry in chain:
@@ -126,26 +129,29 @@ def load_config_from_registry(config_class: type[T]) -> T:
126
129
  try:
127
130
  # Skip async sources in sync context
128
131
  if inspect.iscoroutinefunction(source.load_config):
129
- log.debug("Skipping async config source in sync context", source=entry.name)
132
+ log.debug(
133
+ "Skipping async config source in sync context",
134
+ source=entry.name,
135
+ )
130
136
  continue
131
-
137
+
132
138
  source_data = source.load_config()
133
139
  if source_data:
134
140
  config_data.update(source_data)
135
141
  except Exception as e:
136
142
  log.warning(
137
- "Failed to load config from source",
138
- source=entry.name,
139
- error=str(e)
143
+ "Failed to load config from source",
144
+ source=entry.name,
145
+ error=str(e),
140
146
  )
141
-
147
+
142
148
  # Create config instance
143
149
  return config_class.from_dict(config_data)
144
150
 
145
151
 
146
152
  __all__ = [
147
- "resolve_config_value",
148
- "get_config_chain",
153
+ "get_config_chain",
149
154
  "load_all_configs",
150
155
  "load_config_from_registry",
151
- ]
156
+ "resolve_config_value",
157
+ ]
@@ -12,14 +12,15 @@ from provide.foundation.hub.registry import Registry
12
12
 
13
13
  def _get_registry_and_lock():
14
14
  """Get registry and lock from components module."""
15
- from provide.foundation.hub.components import get_component_registry, _registry_lock
15
+ from provide.foundation.hub.components import _registry_lock, get_component_registry
16
+
16
17
  return get_component_registry(), _registry_lock
17
18
 
18
19
 
19
20
  def resolve_component_dependencies(name: str, dimension: str) -> dict[str, Any]:
20
21
  """Resolve component dependencies recursively."""
21
22
  registry, registry_lock = _get_registry_and_lock()
22
-
23
+
23
24
  with registry_lock:
24
25
  entry = registry.get_entry(name, dimension)
25
26
 
@@ -57,6 +58,6 @@ def discover_components(
57
58
 
58
59
 
59
60
  __all__ = [
60
- "resolve_component_dependencies",
61
61
  "discover_components",
62
- ]
62
+ "resolve_component_dependencies",
63
+ ]