Skip to content

Commit 4f3e48d

Browse files
committed
add missing async, not implemented exceptions and test coverage
1 parent a6b8325 commit 4f3e48d

File tree

3 files changed

+80
-8
lines changed

3 files changed

+80
-8
lines changed

openfeature/provider/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ async def resolve_boolean_details(
174174
default_value: bool,
175175
evaluation_context: typing.Optional[EvaluationContext] = None,
176176
) -> FlagResolutionDetails[bool]:
177-
pass
177+
raise NotImplementedError("Method not implemented")
178178

179179
@abstractmethod
180180
async def resolve_string_details(
@@ -183,7 +183,7 @@ async def resolve_string_details(
183183
default_value: str,
184184
evaluation_context: typing.Optional[EvaluationContext] = None,
185185
) -> FlagResolutionDetails[str]:
186-
pass
186+
raise NotImplementedError("Method not implemented")
187187

188188
@abstractmethod
189189
async def resolve_integer_details(
@@ -192,7 +192,7 @@ async def resolve_integer_details(
192192
default_value: int,
193193
evaluation_context: typing.Optional[EvaluationContext] = None,
194194
) -> FlagResolutionDetails[int]:
195-
pass
195+
raise NotImplementedError("Method not implemented")
196196

197197
@abstractmethod
198198
async def resolve_float_details(
@@ -201,13 +201,13 @@ async def resolve_float_details(
201201
default_value: float,
202202
evaluation_context: typing.Optional[EvaluationContext] = None,
203203
) -> FlagResolutionDetails[float]:
204-
pass
204+
raise NotImplementedError("Method not implemented")
205205

206206
@abstractmethod
207-
def resolve_object_details(
207+
async def resolve_object_details(
208208
self,
209209
flag_key: str,
210210
default_value: typing.Union[dict, list],
211211
evaluation_context: typing.Optional[EvaluationContext] = None,
212212
) -> FlagResolutionDetails[typing.Union[dict, list]]:
213-
pass
213+
raise NotImplementedError("Method not implemented")

openfeature/provider/no_op_provider.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from openfeature.evaluation_context import EvaluationContext
44
from openfeature.flag_evaluation import FlagResolutionDetails, Reason
55
from openfeature.hook import Hook
6-
from openfeature.provider import AbstractProvider, Metadata
6+
from openfeature.provider import AbstractProvider, AsyncAbstractProvider, Metadata
77
from openfeature.provider.no_op_metadata import NoOpMetadata
88

99
PASSED_IN_DEFAULT = "Passed in default"
@@ -77,7 +77,10 @@ def resolve_object_details(
7777
)
7878

7979

80-
class AsyncNoOpProvider(NoOpProvider):
80+
class AsyncNoOpProvider(AsyncAbstractProvider):
81+
def get_metadata(self) -> Metadata:
82+
return NoOpMetadata()
83+
8184
async def resolve_boolean_details(
8285
self,
8386
flag_key: str,

tests/provider/test_no_op_provider.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import typing
12
from numbers import Number
23

4+
import pytest
5+
6+
from openfeature.evaluation_context import EvaluationContext
7+
from openfeature.flag_evaluation import FlagResolutionDetails
8+
from openfeature.provider import AsyncAbstractProvider
39
from openfeature.provider.no_op_provider import NoOpProvider
410

511

@@ -80,3 +86,66 @@ def test_should_resolve_object_flag_from_no_op():
8086
assert flag is not None
8187
assert flag.value == return_value
8288
assert isinstance(flag.value, dict)
89+
90+
91+
class ConcreteAsyncProvider(AsyncAbstractProvider):
92+
def get_metadata(self):
93+
return super().get_metadata()
94+
95+
async def resolve_boolean_details(
96+
self,
97+
flag_key: str,
98+
default_value: bool,
99+
evaluation_context: typing.Optional[EvaluationContext] = None,
100+
) -> FlagResolutionDetails[bool]:
101+
return await super().resolve_boolean_details(flag_key, default_value)
102+
103+
async def resolve_string_details(
104+
self,
105+
flag_key: str,
106+
default_value: str,
107+
evaluation_context: typing.Optional[EvaluationContext] = None,
108+
) -> FlagResolutionDetails[str]:
109+
return await super().resolve_string_details(flag_key, default_value)
110+
111+
async def resolve_integer_details(
112+
self,
113+
flag_key: str,
114+
default_value: int,
115+
evaluation_context: typing.Optional[EvaluationContext] = None,
116+
) -> FlagResolutionDetails[int]:
117+
return await super().resolve_integer_details(flag_key, default_value)
118+
119+
async def resolve_float_details(
120+
self,
121+
flag_key: str,
122+
default_value: float,
123+
evaluation_context: typing.Optional[EvaluationContext] = None,
124+
) -> FlagResolutionDetails[float]:
125+
return await super().resolve_float_details(flag_key, default_value)
126+
127+
async def resolve_object_details(
128+
self,
129+
flag_key: str,
130+
default_value: typing.Union[dict, list],
131+
evaluation_context: typing.Optional[EvaluationContext] = None,
132+
) -> FlagResolutionDetails[typing.Union[dict, list]]:
133+
return await super().resolve_object_details(flag_key, default_value)
134+
135+
136+
@pytest.mark.parametrize(
137+
"get_method, default",
138+
(
139+
("resolve_boolean_details", True),
140+
("resolve_string_details", "default"),
141+
("resolve_integer_details", 42),
142+
("resolve_float_details", 3.14),
143+
("resolve_object_details", {"key": "value"}),
144+
),
145+
)
146+
@pytest.mark.asyncio
147+
async def test_abstract_provider_throws_not_implemented(get_method, default):
148+
with pytest.raises(NotImplementedError) as exception:
149+
provider = ConcreteAsyncProvider()
150+
await getattr(provider, get_method)("test_flag", default)
151+
assert str(exception.value) == "Method not implemented"

0 commit comments

Comments
 (0)