openfeature-provider-flagd 0.2.1__py3-none-any.whl → 0.2.3__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.
- openfeature/contrib/provider/flagd/config.py +9 -0
- openfeature/contrib/provider/flagd/provider.py +12 -10
- openfeature/contrib/provider/flagd/resolvers/in_process.py +30 -4
- openfeature/contrib/provider/flagd/resolvers/process/connector/file_watcher.py +15 -4
- openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py +22 -9
- openfeature/contrib/provider/flagd/resolvers/process/flags.py +41 -5
- openfeature/schemas/protobuf/flagd/evaluation/v1/evaluation_pb2_grpc.py +1 -1
- openfeature/schemas/protobuf/flagd/sync/v1/sync_pb2_grpc.py +1 -1
- openfeature/schemas/protobuf/schema/v1/schema_pb2_grpc.py +1 -1
- openfeature/schemas/protobuf/sync/v1/sync_service_pb2_grpc.py +1 -1
- {openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/METADATA +1 -1
- {openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/RECORD +14 -14
- {openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/WHEEL +0 -0
- {openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -100,6 +100,7 @@ class Config:
|
|
|
100
100
|
cert_path: typing.Optional[str] = None,
|
|
101
101
|
default_authority: typing.Optional[str] = None,
|
|
102
102
|
channel_credentials: typing.Optional[grpc.ChannelCredentials] = None,
|
|
103
|
+
sync_metadata_disabled: typing.Optional[bool] = None,
|
|
103
104
|
):
|
|
104
105
|
self.host = env_or_default(ENV_VAR_HOST, DEFAULT_HOST) if host is None else host
|
|
105
106
|
|
|
@@ -248,3 +249,11 @@ class Config:
|
|
|
248
249
|
)
|
|
249
250
|
|
|
250
251
|
self.channel_credentials = channel_credentials
|
|
252
|
+
|
|
253
|
+
# TODO: remove the metadata call entirely after https://github.com/open-feature/flagd/issues/1584
|
|
254
|
+
# This is a temporary stop-gap solutions to support servers that don't implement sync.GetMetadata
|
|
255
|
+
# (see: https://buf.build/open-feature/flagd/docs/main:flagd.sync.v1#flagd.sync.v1.FlagSyncService.GetMetadata).
|
|
256
|
+
# Using this option disables call to sync.GetMetadata
|
|
257
|
+
# Disabling will prevent static context from flagd being used in evaluations.
|
|
258
|
+
# GetMetadata and this option will be removed.
|
|
259
|
+
self.sync_metadata_disabled = sync_metadata_disabled
|
|
@@ -64,6 +64,7 @@ class FlagdProvider(AbstractProvider):
|
|
|
64
64
|
cert_path: typing.Optional[str] = None,
|
|
65
65
|
default_authority: typing.Optional[str] = None,
|
|
66
66
|
channel_credentials: typing.Optional[grpc.ChannelCredentials] = None,
|
|
67
|
+
sync_metadata_disabled: typing.Optional[bool] = None,
|
|
67
68
|
):
|
|
68
69
|
"""
|
|
69
70
|
Create an instance of the FlagdProvider
|
|
@@ -106,6 +107,7 @@ class FlagdProvider(AbstractProvider):
|
|
|
106
107
|
cert_path=cert_path,
|
|
107
108
|
default_authority=default_authority,
|
|
108
109
|
channel_credentials=channel_credentials,
|
|
110
|
+
sync_metadata_disabled=sync_metadata_disabled,
|
|
109
111
|
)
|
|
110
112
|
self.enriched_context: dict = {}
|
|
111
113
|
|
|
@@ -156,52 +158,52 @@ class FlagdProvider(AbstractProvider):
|
|
|
156
158
|
|
|
157
159
|
def resolve_boolean_details(
|
|
158
160
|
self,
|
|
159
|
-
|
|
161
|
+
flag_key: str,
|
|
160
162
|
default_value: bool,
|
|
161
163
|
evaluation_context: typing.Optional[EvaluationContext] = None,
|
|
162
164
|
) -> FlagResolutionDetails[bool]:
|
|
163
165
|
return self.resolver.resolve_boolean_details(
|
|
164
|
-
|
|
166
|
+
flag_key, default_value, evaluation_context
|
|
165
167
|
)
|
|
166
168
|
|
|
167
169
|
def resolve_string_details(
|
|
168
170
|
self,
|
|
169
|
-
|
|
171
|
+
flag_key: str,
|
|
170
172
|
default_value: str,
|
|
171
173
|
evaluation_context: typing.Optional[EvaluationContext] = None,
|
|
172
174
|
) -> FlagResolutionDetails[str]:
|
|
173
175
|
return self.resolver.resolve_string_details(
|
|
174
|
-
|
|
176
|
+
flag_key, default_value, evaluation_context
|
|
175
177
|
)
|
|
176
178
|
|
|
177
179
|
def resolve_float_details(
|
|
178
180
|
self,
|
|
179
|
-
|
|
181
|
+
flag_key: str,
|
|
180
182
|
default_value: float,
|
|
181
183
|
evaluation_context: typing.Optional[EvaluationContext] = None,
|
|
182
184
|
) -> FlagResolutionDetails[float]:
|
|
183
185
|
return self.resolver.resolve_float_details(
|
|
184
|
-
|
|
186
|
+
flag_key, default_value, evaluation_context
|
|
185
187
|
)
|
|
186
188
|
|
|
187
189
|
def resolve_integer_details(
|
|
188
190
|
self,
|
|
189
|
-
|
|
191
|
+
flag_key: str,
|
|
190
192
|
default_value: int,
|
|
191
193
|
evaluation_context: typing.Optional[EvaluationContext] = None,
|
|
192
194
|
) -> FlagResolutionDetails[int]:
|
|
193
195
|
return self.resolver.resolve_integer_details(
|
|
194
|
-
|
|
196
|
+
flag_key, default_value, evaluation_context
|
|
195
197
|
)
|
|
196
198
|
|
|
197
199
|
def resolve_object_details(
|
|
198
200
|
self,
|
|
199
|
-
|
|
201
|
+
flag_key: str,
|
|
200
202
|
default_value: typing.Union[dict, list],
|
|
201
203
|
evaluation_context: typing.Optional[EvaluationContext] = None,
|
|
202
204
|
) -> FlagResolutionDetails[typing.Union[dict, list]]:
|
|
203
205
|
return self.resolver.resolve_object_details(
|
|
204
|
-
|
|
206
|
+
flag_key, default_value, evaluation_context
|
|
205
207
|
)
|
|
206
208
|
|
|
207
209
|
def emit_provider_ready_with_context(
|
|
@@ -17,6 +17,23 @@ from .process.targeting import targeting
|
|
|
17
17
|
T = typing.TypeVar("T")
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def _merge_metadata(
|
|
21
|
+
flag_metadata: typing.Optional[
|
|
22
|
+
typing.Mapping[str, typing.Union[float, int, str, bool]]
|
|
23
|
+
],
|
|
24
|
+
flag_set_metadata: typing.Optional[
|
|
25
|
+
typing.Mapping[str, typing.Union[float, int, str, bool]]
|
|
26
|
+
],
|
|
27
|
+
) -> typing.Mapping[str, typing.Union[float, int, str, bool]]:
|
|
28
|
+
metadata = {} if flag_set_metadata is None else dict(flag_set_metadata)
|
|
29
|
+
|
|
30
|
+
if flag_metadata is not None:
|
|
31
|
+
for key, value in flag_metadata.items():
|
|
32
|
+
metadata[key] = value
|
|
33
|
+
|
|
34
|
+
return metadata
|
|
35
|
+
|
|
36
|
+
|
|
20
37
|
class InProcessResolver:
|
|
21
38
|
def __init__(
|
|
22
39
|
self,
|
|
@@ -103,29 +120,38 @@ class InProcessResolver:
|
|
|
103
120
|
if not flag:
|
|
104
121
|
raise FlagNotFoundError(f"Flag with key {key} not present in flag store.")
|
|
105
122
|
|
|
123
|
+
metadata = _merge_metadata(flag.metadata, self.flag_store.flag_set_metadata)
|
|
124
|
+
|
|
106
125
|
if flag.state == "DISABLED":
|
|
107
|
-
return FlagResolutionDetails(
|
|
126
|
+
return FlagResolutionDetails(
|
|
127
|
+
default_value, flag_metadata=metadata, reason=Reason.DISABLED
|
|
128
|
+
)
|
|
108
129
|
|
|
109
130
|
if not flag.targeting:
|
|
110
131
|
variant, value = flag.default
|
|
111
|
-
return FlagResolutionDetails(
|
|
132
|
+
return FlagResolutionDetails(
|
|
133
|
+
value, variant=variant, flag_metadata=metadata, reason=Reason.STATIC
|
|
134
|
+
)
|
|
112
135
|
|
|
113
136
|
variant = targeting(flag.key, flag.targeting, evaluation_context)
|
|
114
137
|
|
|
115
138
|
if variant is None:
|
|
116
139
|
variant, value = flag.default
|
|
117
|
-
return FlagResolutionDetails(
|
|
140
|
+
return FlagResolutionDetails(
|
|
141
|
+
value, variant=variant, flag_metadata=metadata, reason=Reason.DEFAULT
|
|
142
|
+
)
|
|
118
143
|
if not isinstance(variant, (str, bool)):
|
|
119
144
|
raise ParseError(
|
|
120
145
|
"Parsed JSONLogic targeting did not return a string or bool"
|
|
121
146
|
)
|
|
122
147
|
|
|
123
148
|
variant, value = flag.get_variant(variant)
|
|
124
|
-
if
|
|
149
|
+
if value is None:
|
|
125
150
|
raise ParseError(f"Resolved variant {variant} not in variants config.")
|
|
126
151
|
|
|
127
152
|
return FlagResolutionDetails(
|
|
128
153
|
value,
|
|
129
154
|
variant=variant,
|
|
130
155
|
reason=Reason.TARGETING_MATCH,
|
|
156
|
+
flag_metadata=metadata,
|
|
131
157
|
)
|
|
@@ -14,7 +14,7 @@ from openfeature.contrib.provider.flagd.resolvers.process.connector import (
|
|
|
14
14
|
from openfeature.contrib.provider.flagd.resolvers.process.flags import FlagStore
|
|
15
15
|
from openfeature.evaluation_context import EvaluationContext
|
|
16
16
|
from openfeature.event import ProviderEventDetails
|
|
17
|
-
from openfeature.exception import ParseError, ProviderNotReadyError
|
|
17
|
+
from openfeature.exception import ErrorCode, ParseError, ProviderNotReadyError
|
|
18
18
|
|
|
19
19
|
logger = logging.getLogger("openfeature.contrib")
|
|
20
20
|
|
|
@@ -76,8 +76,15 @@ class FileWatcher(FlagStateConnector):
|
|
|
76
76
|
self.handle_error("Could not parse JSON flag data from file")
|
|
77
77
|
except yaml.error.YAMLError:
|
|
78
78
|
self.handle_error("Could not parse YAML flag data from file")
|
|
79
|
-
except ParseError:
|
|
80
|
-
self.handle_error(
|
|
79
|
+
except ParseError as e:
|
|
80
|
+
self.handle_error(
|
|
81
|
+
"Could not parse flag data using flagd syntax: "
|
|
82
|
+
+ (
|
|
83
|
+
"no error message provided"
|
|
84
|
+
if e is None or e.error_message is None
|
|
85
|
+
else e.error_message
|
|
86
|
+
)
|
|
87
|
+
)
|
|
81
88
|
except Exception:
|
|
82
89
|
self.handle_error("Could not read flags from file")
|
|
83
90
|
|
|
@@ -104,4 +111,8 @@ class FileWatcher(FlagStateConnector):
|
|
|
104
111
|
def handle_error(self, error_message: str) -> None:
|
|
105
112
|
logger.exception(error_message)
|
|
106
113
|
self.should_emit_ready_on_success = True
|
|
107
|
-
self.emit_provider_error(
|
|
114
|
+
self.emit_provider_error(
|
|
115
|
+
ProviderEventDetails(
|
|
116
|
+
message=error_message, error_code=ErrorCode.PARSE_ERROR
|
|
117
|
+
)
|
|
118
|
+
)
|
|
@@ -6,6 +6,7 @@ import typing
|
|
|
6
6
|
|
|
7
7
|
import grpc
|
|
8
8
|
from google.protobuf.json_format import MessageToDict
|
|
9
|
+
from google.protobuf.struct_pb2 import Struct
|
|
9
10
|
|
|
10
11
|
from openfeature.evaluation_context import EvaluationContext
|
|
11
12
|
from openfeature.event import ProviderEventDetails
|
|
@@ -162,24 +163,36 @@ class GrpcWatcher(FlagStateConnector):
|
|
|
162
163
|
self.active = False
|
|
163
164
|
self.channel.close()
|
|
164
165
|
|
|
166
|
+
def _create_request_args(self) -> dict:
|
|
167
|
+
request_args = {}
|
|
168
|
+
if self.selector is not None:
|
|
169
|
+
request_args["selector"] = self.selector
|
|
170
|
+
if self.provider_id is not None:
|
|
171
|
+
request_args["provider_id"] = self.provider_id
|
|
172
|
+
|
|
173
|
+
return request_args
|
|
174
|
+
|
|
165
175
|
def listen(self) -> None:
|
|
166
176
|
call_args = (
|
|
167
177
|
{"timeout": self.streamline_deadline_seconds}
|
|
168
178
|
if self.streamline_deadline_seconds > 0
|
|
169
179
|
else {}
|
|
170
180
|
)
|
|
171
|
-
request_args =
|
|
172
|
-
if self.selector is not None:
|
|
173
|
-
request_args["selector"] = self.selector
|
|
174
|
-
if self.provider_id is not None:
|
|
175
|
-
request_args["provider_id"] = self.provider_id
|
|
181
|
+
request_args = self._create_request_args()
|
|
176
182
|
|
|
177
183
|
while self.active:
|
|
178
184
|
try:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
185
|
+
context_values_response: sync_pb2.GetMetadataResponse
|
|
186
|
+
if self.config.sync_metadata_disabled:
|
|
187
|
+
context_values_response = sync_pb2.GetMetadataResponse(
|
|
188
|
+
metadata=Struct()
|
|
189
|
+
)
|
|
190
|
+
else:
|
|
191
|
+
context_values_request = sync_pb2.GetMetadataRequest()
|
|
192
|
+
context_values_response = self.stub.GetMetadata(
|
|
193
|
+
context_values_request, wait_for_ready=True
|
|
194
|
+
)
|
|
195
|
+
|
|
183
196
|
context_values = MessageToDict(context_values_response)
|
|
184
197
|
|
|
185
198
|
request = sync_pb2.SyncFlagsRequest(**request_args)
|
|
@@ -7,6 +7,21 @@ from openfeature.event import ProviderEventDetails
|
|
|
7
7
|
from openfeature.exception import ParseError
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
def _validate_metadata(key: str, value: typing.Union[float, int, str, bool]) -> None:
|
|
11
|
+
if key is None:
|
|
12
|
+
raise ParseError("Metadata key must be set")
|
|
13
|
+
elif not isinstance(key, str):
|
|
14
|
+
raise ParseError(f"Metadata key {key} must be of type str, but is {type(key)}")
|
|
15
|
+
elif not key:
|
|
16
|
+
raise ParseError("key must not be empty")
|
|
17
|
+
if value is None:
|
|
18
|
+
raise ParseError(f"Metadata value for key {key} must be set")
|
|
19
|
+
elif not isinstance(value, (float, int, str, bool)):
|
|
20
|
+
raise ParseError(
|
|
21
|
+
f"Metadata value {value} for key {key} must be of type float, int, str or bool, but is {type(value)}"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
10
25
|
class FlagStore:
|
|
11
26
|
def __init__(
|
|
12
27
|
self,
|
|
@@ -16,12 +31,16 @@ class FlagStore:
|
|
|
16
31
|
):
|
|
17
32
|
self.emit_provider_configuration_changed = emit_provider_configuration_changed
|
|
18
33
|
self.flags: typing.Mapping[str, Flag] = {}
|
|
34
|
+
self.flag_set_metadata: typing.Mapping[
|
|
35
|
+
str, typing.Union[float, int, str, bool]
|
|
36
|
+
] = {}
|
|
19
37
|
|
|
20
38
|
def get_flag(self, key: str) -> typing.Optional["Flag"]:
|
|
21
39
|
return self.flags.get(key)
|
|
22
40
|
|
|
23
41
|
def update(self, flags_data: dict) -> None:
|
|
24
42
|
flags = flags_data.get("flags", {})
|
|
43
|
+
metadata = flags_data.get("metadata", {})
|
|
25
44
|
evaluators: typing.Optional[dict] = flags_data.get("$evaluators")
|
|
26
45
|
if evaluators:
|
|
27
46
|
transposed = json.dumps(flags)
|
|
@@ -33,10 +52,18 @@ class FlagStore:
|
|
|
33
52
|
|
|
34
53
|
if not isinstance(flags, dict):
|
|
35
54
|
raise ParseError("`flags` key of configuration must be a dictionary")
|
|
55
|
+
if not isinstance(metadata, dict):
|
|
56
|
+
raise ParseError("`metadata` key of configuration must be a dictionary")
|
|
57
|
+
for key, value in metadata.items():
|
|
58
|
+
_validate_metadata(key, value)
|
|
59
|
+
|
|
36
60
|
self.flags = {key: Flag.from_dict(key, data) for key, data in flags.items()}
|
|
61
|
+
self.flag_set_metadata = metadata
|
|
37
62
|
|
|
38
63
|
self.emit_provider_configuration_changed(
|
|
39
|
-
ProviderEventDetails(
|
|
64
|
+
ProviderEventDetails(
|
|
65
|
+
flags_changed=list(self.flags.keys()), metadata=metadata
|
|
66
|
+
)
|
|
40
67
|
)
|
|
41
68
|
|
|
42
69
|
|
|
@@ -47,6 +74,9 @@ class Flag:
|
|
|
47
74
|
variants: typing.Mapping[str, typing.Any]
|
|
48
75
|
default_variant: typing.Union[bool, str]
|
|
49
76
|
targeting: typing.Optional[dict] = None
|
|
77
|
+
metadata: typing.Optional[
|
|
78
|
+
typing.Mapping[str, typing.Union[float, int, str, bool]]
|
|
79
|
+
] = None
|
|
50
80
|
|
|
51
81
|
def __post_init__(self) -> None:
|
|
52
82
|
if not self.state or not isinstance(self.state, str):
|
|
@@ -66,19 +96,25 @@ class Flag:
|
|
|
66
96
|
if self.default_variant not in self.variants:
|
|
67
97
|
raise ParseError("Default variant does not match set of variants")
|
|
68
98
|
|
|
99
|
+
if self.metadata:
|
|
100
|
+
if not isinstance(self.metadata, dict):
|
|
101
|
+
raise ParseError("Flag metadata is not a valid json object")
|
|
102
|
+
for key, value in self.metadata.items():
|
|
103
|
+
_validate_metadata(key, value)
|
|
104
|
+
|
|
69
105
|
@classmethod
|
|
70
106
|
def from_dict(cls, key: str, data: dict) -> "Flag":
|
|
71
107
|
if "defaultVariant" in data:
|
|
72
108
|
data["default_variant"] = data["defaultVariant"]
|
|
73
109
|
del data["defaultVariant"]
|
|
74
110
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if "selector" in data:
|
|
78
|
-
del data["selector"]
|
|
111
|
+
data.pop("source", None)
|
|
112
|
+
data.pop("selector", None)
|
|
79
113
|
try:
|
|
80
114
|
flag = cls(key=key, **data)
|
|
81
115
|
return flag
|
|
116
|
+
except ParseError as parseError:
|
|
117
|
+
raise parseError
|
|
82
118
|
except Exception as err:
|
|
83
119
|
raise ParseError from err
|
|
84
120
|
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from openfeature.schemas.protobuf.flagd.evaluation.v1 import evaluation_pb2 as openfeature_dot_schemas_dot_protobuf_dot_flagd_dot_evaluation_dot_v1_dot_evaluation__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from openfeature.schemas.protobuf.flagd.sync.v1 import sync_pb2 as openfeature_dot_schemas_dot_protobuf_dot_flagd_dot_sync_dot_v1_dot_sync__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from openfeature.schemas.protobuf.schema.v1 import schema_pb2 as openfeature_dot_schemas_dot_protobuf_dot_schema_dot_v1_dot_schema__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from openfeature.schemas.protobuf.sync.v1 import sync_service_pb2 as openfeature_dot_schemas_dot_protobuf_dot_sync_dot_v1_dot_sync__service__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
{openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openfeature-provider-flagd
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: OpenFeature provider for the flagd flag evaluation engine
|
|
5
5
|
Project-URL: Homepage, https://github.com/open-feature/python-sdk-contrib
|
|
6
6
|
Author-email: OpenFeature <openfeature-core@groups.io>
|
{openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/RECORD
RENAMED
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
openfeature/.gitignore,sha256=1ZPH4VtVL4bMQmBJXQJxeAyUa74LCtqV1a_yjeDIzSQ,8
|
|
2
2
|
openfeature/contrib/provider/flagd/__init__.py,sha256=WlrcPaCH31dEG1IvrvpeuhAaQ8Ni8LEzDpNM_x-qKOA,65
|
|
3
|
-
openfeature/contrib/provider/flagd/config.py,sha256=
|
|
3
|
+
openfeature/contrib/provider/flagd/config.py,sha256=GAt8skBFMzF4skf8l8yr7jl7KBUM509ogZDpvF3NByk,8380
|
|
4
4
|
openfeature/contrib/provider/flagd/flag_type.py,sha256=rZYfmqQEmtqVVTb8e-d8Wt8ZCnHtf7xPSmYxyU8w0R0,158
|
|
5
|
-
openfeature/contrib/provider/flagd/provider.py,sha256=
|
|
5
|
+
openfeature/contrib/provider/flagd/provider.py,sha256=qGLWvpYEfvf5RrvYb2vTvzc8CDrAWausA3bPfs93v3I,7981
|
|
6
6
|
openfeature/contrib/provider/flagd/sync_metadata_hook.py,sha256=fd3uRtwDhVlCW9vZhS35p9qENkl6wDHwlFH-L48aPDM,456
|
|
7
7
|
openfeature/contrib/provider/flagd/resolvers/__init__.py,sha256=CzsnsfxJCaD_S1gBf15kkJBVD-gVLKIwDi4W1nE-dXw,181
|
|
8
8
|
openfeature/contrib/provider/flagd/resolvers/grpc.py,sha256=KJTrwZM-XF2-Xw-O4YvrN-Xvn_KqsO9T29lBAjiDS-4,13581
|
|
9
|
-
openfeature/contrib/provider/flagd/resolvers/in_process.py,sha256=
|
|
9
|
+
openfeature/contrib/provider/flagd/resolvers/in_process.py,sha256=Oqj3Ak-zqjvWnlnsg5ElXXHn-YIPZRItbyfzakCd8O0,5433
|
|
10
10
|
openfeature/contrib/provider/flagd/resolvers/protocol.py,sha256=Wc7oUH6ytPuKg8Lj_3y-_LLkQkuvsow9IiSfmlM8I2o,1402
|
|
11
11
|
openfeature/contrib/provider/flagd/resolvers/process/custom_ops.py,sha256=bZX1At0dRxhghhWz4g-8N-YPobcVfYSv9PTsYh-lZDc,4549
|
|
12
|
-
openfeature/contrib/provider/flagd/resolvers/process/flags.py,sha256=
|
|
12
|
+
openfeature/contrib/provider/flagd/resolvers/process/flags.py,sha256=znDHo84b4-vQswoHSo0807AvK84mqhiJjlC-_vMehdE,4759
|
|
13
13
|
openfeature/contrib/provider/flagd/resolvers/process/targeting.py,sha256=qjYgfoJK9B1ghh19cUq7f-VEql7Hh1J7sh0BhnNc_h0,905
|
|
14
14
|
openfeature/contrib/provider/flagd/resolvers/process/connector/__init__.py,sha256=hyYYxRYEnSho5F28M2hbhhtkG4DQTwJjD36ddI0Xs7M,289
|
|
15
|
-
openfeature/contrib/provider/flagd/resolvers/process/connector/file_watcher.py,sha256=
|
|
16
|
-
openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py,sha256=
|
|
15
|
+
openfeature/contrib/provider/flagd/resolvers/process/connector/file_watcher.py,sha256=abj6DhAyu2nP-P5EAHB9GyceJMym21rO8tKr8nQhmKM,4241
|
|
16
|
+
openfeature/contrib/provider/flagd/resolvers/process/connector/grpc_watcher.py,sha256=XwG71pZqLLEBn7FAT0BhrO1LcCTuEwNZAXvEr37gioY,8835
|
|
17
17
|
openfeature/schemas/protobuf/flagd/evaluation/v1/evaluation_pb2.py,sha256=YPBimdlVBCfnVqxq9uek3H4nyaIR0MhggCAaR0XtIt4,7527
|
|
18
18
|
openfeature/schemas/protobuf/flagd/evaluation/v1/evaluation_pb2.pyi,sha256=afh-fdsmyfS62C-iq7EQsqr_5yZP_QxJXp81Q0Lcllk,18333
|
|
19
|
-
openfeature/schemas/protobuf/flagd/evaluation/v1/evaluation_pb2_grpc.py,sha256=
|
|
19
|
+
openfeature/schemas/protobuf/flagd/evaluation/v1/evaluation_pb2_grpc.py,sha256=owH7bBrwEdzXxvabwv1ebzWVczshLFE3TZcDoAj8Owk,17189
|
|
20
20
|
openfeature/schemas/protobuf/flagd/evaluation/v1/evaluation_pb2_grpc.pyi,sha256=tQm-QOlsMdhdN_7i5LsrtLtBPu4qpL0qzTE7DbSvXFs,7731
|
|
21
21
|
openfeature/schemas/protobuf/flagd/sync/v1/sync_pb2.py,sha256=OIhVrNkhXtwuCdvbahXiOx-mQ3XVVPx5gh0UHzKN0_M,3528
|
|
22
22
|
openfeature/schemas/protobuf/flagd/sync/v1/sync_pb2.pyi,sha256=Qsqe0vz5AJRAAjARXhjiaPKyIFbLttr4gTWae2zyJfM,5967
|
|
23
|
-
openfeature/schemas/protobuf/flagd/sync/v1/sync_pb2_grpc.py,sha256=
|
|
23
|
+
openfeature/schemas/protobuf/flagd/sync/v1/sync_pb2_grpc.py,sha256=gwoXi82VHekdHGuMGvFC0VbNpqVW8tnX2EkkxVDpvzU,8335
|
|
24
24
|
openfeature/schemas/protobuf/flagd/sync/v1/sync_pb2_grpc.pyi,sha256=APjDd-Yo6i6FE_kOusWhTqk-8B_0wIEMXcImCuGpQt8,3782
|
|
25
25
|
openfeature/schemas/protobuf/schema/v1/schema_pb2.py,sha256=dfGpiAYJ2VuRBrctH7s21KkdrIr9rzIaWibUZ3So3g4,7255
|
|
26
26
|
openfeature/schemas/protobuf/schema/v1/schema_pb2.pyi,sha256=14Z6i0kRpCAQO8aCpc4Qwre1OJ7_d_ZIPq8V1vTuYzU,18369
|
|
27
|
-
openfeature/schemas/protobuf/schema/v1/schema_pb2_grpc.py,sha256=
|
|
27
|
+
openfeature/schemas/protobuf/schema/v1/schema_pb2_grpc.py,sha256=af2955mIP2jB9LXZqnfN9cpQbPhl0tTg86MsQzsiy60,16227
|
|
28
28
|
openfeature/schemas/protobuf/schema/v1/schema_pb2_grpc.pyi,sha256=EJ55jvso2Uzx50XryC7fsKGEOBi1bMOGCXaShl1TcJ4,7067
|
|
29
29
|
openfeature/schemas/protobuf/sync/v1/sync_service_pb2.py,sha256=Sw0kLvO0wIRXsaFic8qmTuScMdf1-1WOHGWP4FOIB_s,3327
|
|
30
30
|
openfeature/schemas/protobuf/sync/v1/sync_service_pb2.pyi,sha256=o3YpW_5iQJWjU7IFEsyspeqLyBDC4C_psBNErwziumE,7986
|
|
31
|
-
openfeature/schemas/protobuf/sync/v1/sync_service_pb2_grpc.py,sha256=
|
|
31
|
+
openfeature/schemas/protobuf/sync/v1/sync_service_pb2_grpc.py,sha256=Fnkq2H0sfLwc029RXfFxp5__f4UskT6Hbn_ZBT0LpJU,6185
|
|
32
32
|
openfeature/schemas/protobuf/sync/v1/sync_service_pb2_grpc.pyi,sha256=4NoAkGicVNxx4yVK5_JvvPn1OGlRdPhqM2wCpkwCjEI,3024
|
|
33
|
-
openfeature_provider_flagd-0.2.
|
|
34
|
-
openfeature_provider_flagd-0.2.
|
|
35
|
-
openfeature_provider_flagd-0.2.
|
|
36
|
-
openfeature_provider_flagd-0.2.
|
|
33
|
+
openfeature_provider_flagd-0.2.3.dist-info/METADATA,sha256=IJr2mO2YiYPH4dKlzgLhqHAiweqcjpSk5ftGelFrZws,21635
|
|
34
|
+
openfeature_provider_flagd-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
35
|
+
openfeature_provider_flagd-0.2.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
36
|
+
openfeature_provider_flagd-0.2.3.dist-info/RECORD,,
|
{openfeature_provider_flagd-0.2.1.dist-info → openfeature_provider_flagd-0.2.3.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|