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
@@ -8,6 +8,9 @@ Provides utilities for resetting logger state, managing configurations,
8
8
  and ensuring test isolation for the Foundation logging system.
9
9
  """
10
10
 
11
+ from unittest.mock import Mock
12
+
13
+ import pytest
11
14
  import structlog
12
15
 
13
16
  from provide.foundation.logger.core import (
@@ -17,6 +20,78 @@ from provide.foundation.logger.core import (
17
20
  from provide.foundation.streams.file import reset_streams
18
21
 
19
22
 
23
+ @pytest.fixture
24
+ def mock_logger():
25
+ """
26
+ Comprehensive mock logger for testing.
27
+
28
+ Provides compatibility with both stdlib logging and structlog interfaces,
29
+ including method call tracking and common logger attributes.
30
+
31
+ Returns:
32
+ Mock logger with debug, info, warning, error methods and structlog compatibility.
33
+ """
34
+ logger = Mock()
35
+ logger.debug = Mock()
36
+ logger.info = Mock()
37
+ logger.warning = Mock()
38
+ logger.warn = Mock() # Alias for warning
39
+ logger.error = Mock()
40
+ logger.exception = Mock()
41
+ logger.critical = Mock()
42
+ logger.fatal = Mock() # Alias for critical
43
+
44
+ # Add common logger attributes
45
+ logger.name = "mock_logger"
46
+ logger.level = 10 # DEBUG level
47
+ logger.handlers = []
48
+ logger.disabled = False
49
+
50
+ # Add structlog compatibility methods
51
+ logger.bind = Mock(return_value=logger)
52
+ logger.unbind = Mock(return_value=logger)
53
+ logger.new = Mock(return_value=logger)
54
+ logger.msg = Mock() # Alternative to info
55
+
56
+ # Add trace method for Foundation's extended logging
57
+ logger.trace = Mock()
58
+
59
+ return logger
60
+
61
+
62
+ def mock_logger_factory():
63
+ """
64
+ Factory function to create mock loggers outside of pytest context.
65
+
66
+ Useful for unit tests that need a mock logger but aren't using pytest fixtures.
67
+
68
+ Returns:
69
+ Mock logger with the same interface as the pytest fixture.
70
+ """
71
+ logger = Mock()
72
+ logger.debug = Mock()
73
+ logger.info = Mock()
74
+ logger.warning = Mock()
75
+ logger.warn = Mock()
76
+ logger.error = Mock()
77
+ logger.exception = Mock()
78
+ logger.critical = Mock()
79
+ logger.fatal = Mock()
80
+
81
+ logger.name = "mock_logger"
82
+ logger.level = 10
83
+ logger.handlers = []
84
+ logger.disabled = False
85
+
86
+ logger.bind = Mock(return_value=logger)
87
+ logger.unbind = Mock(return_value=logger)
88
+ logger.new = Mock(return_value=logger)
89
+ logger.msg = Mock()
90
+ logger.trace = Mock()
91
+
92
+ return logger
93
+
94
+
20
95
  def _reset_opentelemetry_providers() -> None:
21
96
  """
22
97
  Reset OpenTelemetry providers to uninitialized state.
@@ -27,7 +102,7 @@ def _reset_opentelemetry_providers() -> None:
27
102
  try:
28
103
  # Reset tracing provider more thoroughly
29
104
  import opentelemetry.trace as otel_trace
30
-
105
+
31
106
  # Reset the Once flag to allow re-initialization
32
107
  if hasattr(otel_trace, "_TRACER_PROVIDER_SET_ONCE"):
33
108
  once_obj = otel_trace._TRACER_PROVIDER_SET_ONCE
@@ -36,11 +111,12 @@ def _reset_opentelemetry_providers() -> None:
36
111
  if hasattr(once_obj, "_lock"):
37
112
  with once_obj._lock:
38
113
  once_obj._done = False
39
-
114
+
40
115
  # Reset to NoOpTracerProvider
41
116
  from opentelemetry.trace import NoOpTracerProvider
117
+
42
118
  otel_trace.set_tracer_provider(NoOpTracerProvider())
43
-
119
+
44
120
  except ImportError:
45
121
  # OpenTelemetry tracing not available
46
122
  pass
@@ -52,7 +128,7 @@ def _reset_opentelemetry_providers() -> None:
52
128
  # Reset metrics provider more thoroughly
53
129
  import opentelemetry.metrics as otel_metrics
54
130
  import opentelemetry.metrics._internal as otel_metrics_internal
55
-
131
+
56
132
  # Reset the Once flag to allow re-initialization
57
133
  if hasattr(otel_metrics_internal, "_METER_PROVIDER_SET_ONCE"):
58
134
  once_obj = otel_metrics_internal._METER_PROVIDER_SET_ONCE
@@ -61,11 +137,12 @@ def _reset_opentelemetry_providers() -> None:
61
137
  if hasattr(once_obj, "_lock"):
62
138
  with once_obj._lock:
63
139
  once_obj._done = False
64
-
140
+
65
141
  # Reset to NoOpMeterProvider
66
142
  from opentelemetry.metrics import NoOpMeterProvider
143
+
67
144
  otel_metrics.set_meter_provider(NoOpMeterProvider())
68
-
145
+
69
146
  except ImportError:
70
147
  # OpenTelemetry metrics not available
71
148
  pass
@@ -113,17 +190,19 @@ def reset_foundation_setup_for_testing() -> None:
113
190
  """
114
191
  # Full reset but with improved OpenTelemetry handling
115
192
  reset_foundation_state()
116
-
193
+
117
194
  # Clear and re-initialize the hub for test isolation
118
195
  try:
119
196
  from provide.foundation.hub.manager import clear_hub
197
+
120
198
  clear_hub()
121
199
  except ImportError:
122
200
  pass
123
-
201
+
124
202
  # Re-register HTTP transport for tests that need it
125
203
  try:
126
204
  from provide.foundation.transport.http import _register_http_transport
205
+
127
206
  _register_http_transport()
128
207
  except ImportError:
129
208
  # Transport module not available
@@ -131,6 +210,8 @@ def reset_foundation_setup_for_testing() -> None:
131
210
 
132
211
 
133
212
  __all__ = [
213
+ "mock_logger",
214
+ "mock_logger_factory",
134
215
  "reset_foundation_setup_for_testing",
135
216
  "reset_foundation_state",
136
217
  ]
@@ -6,41 +6,41 @@ boilerplate and ensure consistent mocking across all tests.
6
6
  """
7
7
 
8
8
  from provide.foundation.testing.mocking.fixtures import (
9
- Mock,
10
- MagicMock,
9
+ ANY,
11
10
  AsyncMock,
11
+ MagicMock,
12
+ Mock,
12
13
  PropertyMock,
13
- patch,
14
+ assert_mock_calls,
15
+ async_mock_factory,
16
+ auto_patch,
14
17
  call,
15
- ANY,
16
- mock_factory,
17
18
  magic_mock_factory,
18
- async_mock_factory,
19
- property_mock_factory,
19
+ mock_factory,
20
+ mock_open_fixture,
21
+ patch,
20
22
  patch_fixture,
21
23
  patch_multiple_fixture,
22
- auto_patch,
23
- mock_open_fixture,
24
+ property_mock_factory,
24
25
  spy_fixture,
25
- assert_mock_calls,
26
26
  )
27
27
 
28
28
  __all__ = [
29
- "Mock",
30
- "MagicMock",
29
+ "ANY",
31
30
  "AsyncMock",
31
+ "MagicMock",
32
+ "Mock",
32
33
  "PropertyMock",
33
- "patch",
34
+ "assert_mock_calls",
35
+ "async_mock_factory",
36
+ "auto_patch",
34
37
  "call",
35
- "ANY",
36
- "mock_factory",
37
38
  "magic_mock_factory",
38
- "async_mock_factory",
39
- "property_mock_factory",
39
+ "mock_factory",
40
+ "mock_open_fixture",
41
+ "patch",
40
42
  "patch_fixture",
41
43
  "patch_multiple_fixture",
42
- "auto_patch",
43
- "mock_open_fixture",
44
+ "property_mock_factory",
44
45
  "spy_fixture",
45
- "assert_mock_calls",
46
- ]
46
+ ]
@@ -5,10 +5,8 @@ Standardized mocking patterns and fixtures for the provide-io ecosystem.
5
5
  Reduces boilerplate and ensures consistent mocking across all tests.
6
6
  """
7
7
 
8
- from unittest.mock import Mock, MagicMock, AsyncMock, PropertyMock, patch, call, ANY
9
- from typing import Any, Callable
10
- from collections.abc import Generator
11
- import sys
8
+ from typing import Any
9
+ from unittest.mock import ANY, AsyncMock, MagicMock, Mock, PropertyMock, call, patch
12
10
 
13
11
  import pytest
14
12
 
@@ -17,18 +15,19 @@ import pytest
17
15
  def mock_factory():
18
16
  """
19
17
  Factory for creating configured mock objects.
20
-
18
+
21
19
  Returns:
22
20
  Function that creates mock objects with common configurations.
23
21
  """
24
- def _create_mock(name: str = None, **kwargs) -> Mock:
22
+
23
+ def _create_mock(name: str | None = None, **kwargs) -> Mock:
25
24
  """
26
25
  Create a mock with standard configuration.
27
-
26
+
28
27
  Args:
29
28
  name: Optional name for the mock
30
29
  **kwargs: Additional mock configuration
31
-
30
+
32
31
  Returns:
33
32
  Configured Mock object
34
33
  """
@@ -36,10 +35,10 @@ def mock_factory():
36
35
  "spec_set": True if "spec" in kwargs else False,
37
36
  }
38
37
  defaults.update(kwargs)
39
-
38
+
40
39
  mock = Mock(name=name, **defaults)
41
40
  return mock
42
-
41
+
43
42
  return _create_mock
44
43
 
45
44
 
@@ -47,23 +46,24 @@ def mock_factory():
47
46
  def magic_mock_factory():
48
47
  """
49
48
  Factory for creating MagicMock objects.
50
-
49
+
51
50
  Returns:
52
51
  Function that creates MagicMock objects with common configurations.
53
52
  """
54
- def _create_magic_mock(name: str = None, **kwargs) -> MagicMock:
53
+
54
+ def _create_magic_mock(name: str | None = None, **kwargs) -> MagicMock:
55
55
  """
56
56
  Create a MagicMock with standard configuration.
57
-
57
+
58
58
  Args:
59
59
  name: Optional name for the mock
60
60
  **kwargs: Additional mock configuration
61
-
61
+
62
62
  Returns:
63
63
  Configured MagicMock object
64
64
  """
65
65
  return MagicMock(name=name, **kwargs)
66
-
66
+
67
67
  return _create_magic_mock
68
68
 
69
69
 
@@ -71,20 +71,23 @@ def magic_mock_factory():
71
71
  def async_mock_factory():
72
72
  """
73
73
  Factory for creating AsyncMock objects.
74
-
74
+
75
75
  Returns:
76
76
  Function that creates AsyncMock objects with common configurations.
77
77
  """
78
- def _create_async_mock(name: str = None, return_value=None, side_effect=None, **kwargs) -> AsyncMock:
78
+
79
+ def _create_async_mock(
80
+ name: str | None = None, return_value: object = None, side_effect: object = None, **kwargs
81
+ ) -> AsyncMock:
79
82
  """
80
83
  Create an AsyncMock with standard configuration.
81
-
84
+
82
85
  Args:
83
86
  name: Optional name for the mock
84
87
  return_value: Return value for the async mock
85
88
  side_effect: Side effect for the async mock
86
89
  **kwargs: Additional mock configuration
87
-
90
+
88
91
  Returns:
89
92
  Configured AsyncMock object
90
93
  """
@@ -94,7 +97,7 @@ def async_mock_factory():
94
97
  if side_effect is not None:
95
98
  mock.side_effect = side_effect
96
99
  return mock
97
-
100
+
98
101
  return _create_async_mock
99
102
 
100
103
 
@@ -102,24 +105,29 @@ def async_mock_factory():
102
105
  def property_mock_factory():
103
106
  """
104
107
  Factory for creating PropertyMock objects.
105
-
108
+
106
109
  Returns:
107
110
  Function that creates PropertyMock objects.
108
111
  """
109
- def _create_property_mock(return_value=None, side_effect=None, **kwargs) -> PropertyMock:
112
+
113
+ def _create_property_mock(
114
+ return_value=None, side_effect=None, **kwargs
115
+ ) -> PropertyMock:
110
116
  """
111
117
  Create a PropertyMock.
112
-
118
+
113
119
  Args:
114
120
  return_value: Return value for the property
115
121
  side_effect: Side effect for the property
116
122
  **kwargs: Additional mock configuration
117
-
123
+
118
124
  Returns:
119
125
  Configured PropertyMock object
120
126
  """
121
- return PropertyMock(return_value=return_value, side_effect=side_effect, **kwargs)
122
-
127
+ return PropertyMock(
128
+ return_value=return_value, side_effect=side_effect, **kwargs
129
+ )
130
+
123
131
  return _create_property_mock
124
132
 
125
133
 
@@ -127,20 +135,20 @@ def property_mock_factory():
127
135
  def patch_fixture():
128
136
  """
129
137
  Fixture for patching objects with automatic cleanup.
130
-
138
+
131
139
  Returns:
132
140
  Function that patches objects and returns the mock.
133
141
  """
134
142
  patches = []
135
-
143
+
136
144
  def _patch(target: str, **kwargs) -> Mock:
137
145
  """
138
146
  Patch a target with automatic cleanup.
139
-
147
+
140
148
  Args:
141
149
  target: The target to patch (module.Class.attribute)
142
150
  **kwargs: Additional patch configuration
143
-
151
+
144
152
  Returns:
145
153
  The mock object
146
154
  """
@@ -148,9 +156,9 @@ def patch_fixture():
148
156
  mock = patcher.start()
149
157
  patches.append(patcher)
150
158
  return mock
151
-
159
+
152
160
  yield _patch
153
-
161
+
154
162
  # Cleanup all patches
155
163
  for patcher in patches:
156
164
  patcher.stop()
@@ -160,31 +168,32 @@ def patch_fixture():
160
168
  def patch_multiple_fixture():
161
169
  """
162
170
  Fixture for patching multiple objects at once.
163
-
171
+
164
172
  Returns:
165
173
  Function that patches multiple targets.
166
174
  """
167
175
  patches = []
168
-
176
+
169
177
  def _patch_multiple(target_module: str, **kwargs) -> dict[str, Mock]:
170
178
  """
171
179
  Patch multiple attributes in a module.
172
-
180
+
173
181
  Args:
174
182
  target_module: The module to patch in
175
183
  **kwargs: Mapping of attribute names to mock objects or DEFAULT
176
-
184
+
177
185
  Returns:
178
186
  Dict mapping attribute names to mock objects
179
187
  """
180
188
  from unittest.mock import patch as mock_patch
189
+
181
190
  patcher = mock_patch.multiple(target_module, **kwargs)
182
191
  mocks = patcher.start()
183
192
  patches.append(patcher)
184
193
  return mocks
185
-
194
+
186
195
  yield _patch_multiple
187
-
196
+
188
197
  # Cleanup all patches
189
198
  for patcher in patches:
190
199
  patcher.stop()
@@ -194,39 +203,41 @@ def patch_multiple_fixture():
194
203
  def auto_patch():
195
204
  """
196
205
  Context manager for automatic patching with cleanup.
197
-
206
+
198
207
  Returns:
199
208
  Patch context manager class.
200
209
  """
210
+
201
211
  class AutoPatch:
202
212
  def __init__(self):
203
213
  self.patches = []
204
-
214
+
205
215
  def object(self, target: Any, attribute: str, **kwargs) -> Mock:
206
216
  """Patch an object's attribute."""
207
217
  patcher = patch.object(target, attribute, **kwargs)
208
218
  mock = patcher.start()
209
219
  self.patches.append(patcher)
210
220
  return mock
211
-
221
+
212
222
  def dict(self, target: dict, values: dict, **kwargs) -> None:
213
223
  """Patch a dictionary."""
214
224
  patcher = patch.dict(target, values, **kwargs)
215
225
  patcher.start()
216
226
  self.patches.append(patcher)
217
-
227
+
218
228
  def env(self, **env_vars) -> None:
219
229
  """Patch environment variables."""
220
230
  import os
231
+
221
232
  patcher = patch.dict(os.environ, env_vars)
222
233
  patcher.start()
223
234
  self.patches.append(patcher)
224
-
235
+
225
236
  def cleanup(self):
226
237
  """Stop all patches."""
227
238
  for patcher in self.patches:
228
239
  patcher.stop()
229
-
240
+
230
241
  patcher = AutoPatch()
231
242
  yield patcher
232
243
  patcher.cleanup()
@@ -236,24 +247,24 @@ def auto_patch():
236
247
  def mock_open_fixture():
237
248
  """
238
249
  Fixture for mocking file operations.
239
-
250
+
240
251
  Returns:
241
252
  Function that creates a mock for open().
242
253
  """
243
254
  from unittest.mock import mock_open
244
-
255
+
245
256
  def _mock_open(read_data: str = None) -> Mock:
246
257
  """
247
258
  Create a mock for the open() builtin.
248
-
259
+
249
260
  Args:
250
261
  read_data: Optional data to return when reading
251
-
262
+
252
263
  Returns:
253
264
  Mock object for open()
254
265
  """
255
266
  return mock_open(read_data=read_data)
256
-
267
+
257
268
  return _mock_open
258
269
 
259
270
 
@@ -261,18 +272,19 @@ def mock_open_fixture():
261
272
  def spy_fixture():
262
273
  """
263
274
  Create a spy (mock that calls through to the original).
264
-
275
+
265
276
  Returns:
266
277
  Function that creates spy objects.
267
278
  """
279
+
268
280
  def _create_spy(obj: Any, method_name: str) -> Mock:
269
281
  """
270
282
  Create a spy on a method.
271
-
283
+
272
284
  Args:
273
285
  obj: The object to spy on
274
286
  method_name: The method name to spy on
275
-
287
+
276
288
  Returns:
277
289
  Mock that wraps the original method
278
290
  """
@@ -280,7 +292,7 @@ def spy_fixture():
280
292
  mock = Mock(wraps=original)
281
293
  setattr(obj, method_name, mock)
282
294
  return mock
283
-
295
+
284
296
  return _create_spy
285
297
 
286
298
 
@@ -288,14 +300,15 @@ def spy_fixture():
288
300
  def assert_mock_calls():
289
301
  """
290
302
  Helper for asserting mock calls with better error messages.
291
-
303
+
292
304
  Returns:
293
305
  Function for asserting mock calls.
294
306
  """
307
+
295
308
  def _assert_calls(mock: Mock, expected_calls: list, any_order: bool = False):
296
309
  """
297
310
  Assert that a mock was called with expected calls.
298
-
311
+
299
312
  Args:
300
313
  mock: The mock to check
301
314
  expected_calls: List of expected call objects
@@ -305,27 +318,27 @@ def assert_mock_calls():
305
318
  mock.assert_has_calls(expected_calls, any_order=True)
306
319
  else:
307
320
  mock.assert_has_calls(expected_calls)
308
-
321
+
309
322
  return _assert_calls
310
323
 
311
324
 
312
325
  # Re-export commonly used mock utilities
313
326
  __all__ = [
314
- "Mock",
315
- "MagicMock",
327
+ "ANY",
316
328
  "AsyncMock",
329
+ "MagicMock",
330
+ "Mock",
317
331
  "PropertyMock",
318
- "patch",
332
+ "assert_mock_calls",
333
+ "async_mock_factory",
334
+ "auto_patch",
319
335
  "call",
320
- "ANY",
321
- "mock_factory",
322
336
  "magic_mock_factory",
323
- "async_mock_factory",
324
- "property_mock_factory",
337
+ "mock_factory",
338
+ "mock_open_fixture",
339
+ "patch",
325
340
  "patch_fixture",
326
341
  "patch_multiple_fixture",
327
- "auto_patch",
328
- "mock_open_fixture",
342
+ "property_mock_factory",
329
343
  "spy_fixture",
330
- "assert_mock_calls",
331
- ]
344
+ ]
@@ -6,43 +6,43 @@ event loop management across any project that depends on provide.foundation.
6
6
  """
7
7
 
8
8
  from provide.foundation.testing.process.fixtures import (
9
- clean_event_loop,
10
- async_timeout,
11
- mock_async_process,
12
- async_stream_reader,
13
- event_loop_policy,
9
+ async_condition_waiter,
14
10
  async_context_manager,
11
+ async_gather_helper,
15
12
  async_iterator,
16
- async_queue,
17
13
  async_lock,
18
- mock_async_sleep,
19
- async_subprocess,
20
- async_gather_helper,
21
- async_task_group,
22
- async_condition_waiter,
23
14
  async_mock_server,
24
15
  async_pipeline,
16
+ async_queue,
25
17
  async_rate_limiter,
18
+ async_stream_reader,
19
+ async_subprocess,
20
+ async_task_group,
26
21
  async_test_client,
22
+ async_timeout,
23
+ clean_event_loop,
24
+ event_loop_policy,
25
+ mock_async_process,
26
+ mock_async_sleep,
27
27
  )
28
28
 
29
29
  __all__ = [
30
- "clean_event_loop",
31
- "async_timeout",
32
- "mock_async_process",
33
- "async_stream_reader",
34
- "event_loop_policy",
30
+ "async_condition_waiter",
35
31
  "async_context_manager",
32
+ "async_gather_helper",
36
33
  "async_iterator",
37
- "async_queue",
38
34
  "async_lock",
39
- "mock_async_sleep",
40
- "async_subprocess",
41
- "async_gather_helper",
42
- "async_task_group",
43
- "async_condition_waiter",
44
35
  "async_mock_server",
45
36
  "async_pipeline",
37
+ "async_queue",
46
38
  "async_rate_limiter",
39
+ "async_stream_reader",
40
+ "async_subprocess",
41
+ "async_task_group",
47
42
  "async_test_client",
48
- ]
43
+ "async_timeout",
44
+ "clean_event_loop",
45
+ "event_loop_policy",
46
+ "mock_async_process",
47
+ "mock_async_sleep",
48
+ ]