|
12 | 12 | from openfeature.event import ProviderEvent, ProviderEventDetails |
13 | 13 | from openfeature.hook import Hook |
14 | 14 | from openfeature.isolated import OpenFeatureAPI, create_api |
15 | | -from openfeature.provider import FeatureProvider, ProviderStatus |
| 15 | +from openfeature.provider import FeatureProvider, Metadata, ProviderStatus |
16 | 16 | from openfeature.provider.no_op_provider import NoOpProvider |
17 | 17 | from openfeature.transaction_context import ContextVarsTransactionContextPropagator |
18 | 18 |
|
@@ -46,8 +46,10 @@ def test_isolated_instance_is_openfeature_api(): |
46 | 46 | _ISOLATED_API_PUBLIC_METHODS = ( |
47 | 47 | "add_handler", |
48 | 48 | "add_hooks", |
| 49 | + "clear_evaluation_context", |
49 | 50 | "clear_hooks", |
50 | 51 | "clear_providers", |
| 52 | + "clear_transaction_context_propagator", |
51 | 53 | "get_client", |
52 | 54 | "get_evaluation_context", |
53 | 55 | "get_hooks", |
@@ -189,6 +191,37 @@ def test_provider_can_be_rebound_after_being_released(): |
189 | 191 | assert api2.get_provider() is provider |
190 | 192 |
|
191 | 193 |
|
| 194 | +def test_set_provider_rejects_non_weak_referenceable_provider(): |
| 195 | + """Providers must be weak-referenceable so the SDK can track bindings |
| 196 | + without leaking memory; surfacing this requirement up front (rather than |
| 197 | + silently skipping the spec 1.8.4 check) avoids hard-to-diagnose bugs.""" |
| 198 | + |
| 199 | + # A direct ``object`` subclass with ``__slots__`` and no ``__weakref__`` |
| 200 | + # entry; instances are not weak-referenceable. Implements the |
| 201 | + # ``FeatureProvider`` protocol structurally rather than via inheritance |
| 202 | + # (which would inherit ``__weakref__`` from the parent class). |
| 203 | + class NotWeakReferenceable: |
| 204 | + __slots__ = () |
| 205 | + |
| 206 | + def attach(self, on_emit): |
| 207 | + pass |
| 208 | + |
| 209 | + def detach(self): |
| 210 | + pass |
| 211 | + |
| 212 | + def get_metadata(self): |
| 213 | + return Metadata(name="not-weak-referenceable") |
| 214 | + |
| 215 | + def get_provider_hooks(self): |
| 216 | + return [] |
| 217 | + |
| 218 | + provider = NotWeakReferenceable() |
| 219 | + api_instance = create_api() |
| 220 | + |
| 221 | + with pytest.raises(TypeError, match="weak-referenceable"): |
| 222 | + api_instance.set_provider(provider) # type: ignore[arg-type] |
| 223 | + |
| 224 | + |
192 | 225 | # --- Isolated state: hooks --- |
193 | 226 |
|
194 | 227 |
|
|
0 commit comments