Skip to content

Commit 126f42f

Browse files
aepflileakonvalinka
andcommitted
fixup: no default value feature added, as testharness is broken otherwise
Signed-off-by: Simon Schrottner <[email protected]> Co-authored-by: Lea Konvalinka <[email protected]>
1 parent a2c88f0 commit 126f42f

File tree

8 files changed

+61
-11
lines changed

8 files changed

+61
-11
lines changed

providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/in_process.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
)
66
from openfeature.evaluation_context import EvaluationContext
77
from openfeature.event import ProviderEventDetails
8-
from openfeature.exception import FlagNotFoundError, GeneralError, ParseError
8+
from openfeature.exception import FlagNotFoundError, GeneralError, ParseError, ErrorCode
99
from openfeature.flag_evaluation import FlagResolutionDetails, Reason
1010

1111
from ..config import Config
@@ -129,6 +129,14 @@ def _resolve(
129129

130130
if not flag.targeting:
131131
variant, value = flag.default
132+
if variant is None:
133+
return FlagResolutionDetails(
134+
value,
135+
variant=variant,
136+
reason=Reason.ERROR,
137+
error_code=ErrorCode.FLAG_NOT_FOUND,
138+
flag_metadata=metadata,
139+
)
132140
if variant not in flag.variants:
133141
raise GeneralError(
134142
f"Resolved variant {variant} not in variants config."
@@ -141,14 +149,27 @@ def _resolve(
141149
variant = targeting(flag.key, flag.targeting, evaluation_context)
142150
if variant is None:
143151
variant, value = flag.default
152+
if variant is None:
153+
return FlagResolutionDetails(
154+
value,
155+
variant=variant,
156+
reason=Reason.ERROR,
157+
error_code=ErrorCode.FLAG_NOT_FOUND,
158+
flag_metadata=metadata,
159+
)
144160
return FlagResolutionDetails(
145161
value,
146162
variant=variant,
147163
flag_metadata=metadata,
148164
reason=Reason.DEFAULT,
149165
)
150166

151-
variant = str(variant).lower() # convert to string to support shorthand
167+
# convert to string to support shorthand (boolean in python is with capital T hence the special case)
168+
if isinstance(variant, bool):
169+
variant = str(variant).lower()
170+
elif not isinstance(variant, str):
171+
variant = str(variant)
172+
152173
if variant not in flag.variants:
153174
raise GeneralError(
154175
f"Resolved variant {variant} not in variants config."

providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/flags.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class Flag:
7272
key: str
7373
state: str
7474
variants: typing.Mapping[str, typing.Any]
75-
default_variant: typing.Union[bool, str]
75+
default_variant: typing.Optional[typing.Union[bool, str]] = None
7676
targeting: typing.Optional[dict] = None
7777
metadata: typing.Optional[
7878
typing.Mapping[str, typing.Union[float, int, str, bool]]
@@ -85,7 +85,7 @@ def __post_init__(self) -> None:
8585
if not self.variants or not isinstance(self.variants, dict):
8686
raise ParseError("Incorrect 'variants' value provided in flag config")
8787

88-
if not self.default_variant or not isinstance(self.default_variant, str):
88+
if self.default_variant and not isinstance(self.default_variant, str):
8989
raise ParseError("Incorrect 'defaultVariant' value provided in flag config")
9090

9191
if self.metadata:
@@ -98,6 +98,8 @@ def __post_init__(self) -> None:
9898
def from_dict(cls, key: str, data: dict) -> "Flag":
9999
if "defaultVariant" in data:
100100
data["default_variant"] = data["defaultVariant"]
101+
if data["default_variant"] is "":
102+
data["default_variant"] = None
101103
del data["defaultVariant"]
102104

103105
data.pop("source", None)
@@ -111,13 +113,16 @@ def from_dict(cls, key: str, data: dict) -> "Flag":
111113
raise ParseError from err
112114

113115
@property
114-
def default(self) -> tuple[str, typing.Any]:
116+
def default(self) -> tuple[typing.Optional[str], typing.Any]:
115117
return self.get_variant(self.default_variant)
116118

117119
def get_variant(
118-
self, variant_key: typing.Union[str, bool]
119-
) -> tuple[str, typing.Any]:
120+
self, variant_key: typing.Union[str, bool, None]
121+
) -> tuple[typing.Optional[str], typing.Any]:
120122
if isinstance(variant_key, bool):
121123
variant_key = str(variant_key).lower()
122124

125+
if not variant_key:
126+
return None, None
127+
123128
return variant_key, self.variants.get(variant_key)

providers/openfeature-provider-flagd/tests/e2e/file/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
"~sync",
1313
"~caching",
1414
"~grace",
15-
"~contextEnrichment",
16-
"~no-default",
15+
"~contextEnrichment"
1716
}
1817

1918

providers/openfeature-provider-flagd/tests/e2e/inprocess/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from tests.e2e.testfilter import TestFilter
55

66
resolver = ResolverType.IN_PROCESS
7-
feature_list = ["~targetURI", "~unixsocket", "~no-default"]
7+
feature_list = ["~targetURI", "~unixsocket"]
88

99

1010
def pytest_collection_modifyitems(config, items):

providers/openfeature-provider-flagd/tests/e2e/rpc/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from tests.e2e.testfilter import TestFilter
55

66
resolver = ResolverType.RPC
7-
feature_list = ["~targetURI", "~unixsocket", "~sync", "~metadata", "~no-default"]
7+
feature_list = ["~targetURI", "~unixsocket", "~sync", "~metadata"]
88

99

1010
def pytest_collection_modifyitems(config, items):

providers/openfeature-provider-flagd/tests/e2e/step/context_steps.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ def update_context(
3535
"""a context containing a key and value."""
3636
evaluation_context.attributes[key] = type_cast[type_info](value)
3737

38+
@given(
39+
parsers.cfparse(
40+
'a context containing a key "{key}", with type "{type_info}" and with value ""'
41+
),
42+
)
43+
def update_context_without_value(
44+
evaluation_context: EvaluationContext, key: str, type_info: str
45+
):
46+
"""a context containing a key and value."""
47+
update_context(evaluation_context, key, type_info, "")
48+
49+
3850

3951
@when(
4052
parsers.cfparse(
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"flags": {
3+
"basic-flag": {
4+
"state": "ENABLED",
5+
"variants": {
6+
"true": true,
7+
"false": false
8+
},
9+
"targeting": {}
10+
}
11+
}
12+
}

providers/openfeature-provider-flagd/tests/test_file_store.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def create_client(provider: FlagdProvider):
2121
"file_name",
2222
[
2323
"basic-flag.json",
24+
"basic-flag-without-default.json",
2425
"basic-flag.yaml",
2526
],
2627
)

0 commit comments

Comments
 (0)