gofeatureflag-python-provider 0.1.1__tar.gz → 0.2.0__tar.gz
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.
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/PKG-INFO +7 -7
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/README.md +5 -5
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/provider.py +18 -71
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/response_flag_evaluation.py +1 -1
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/pyproject.toml +2 -2
- gofeatureflag_python_provider-0.1.1/gofeatureflag_python_provider/provider_status.py +0 -9
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/__init__.py +0 -0
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/data_collector_hook.py +0 -0
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/metadata.py +0 -0
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/options.py +0 -0
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/request_data_collector.py +0 -0
- {gofeatureflag_python_provider-0.1.1 → gofeatureflag_python_provider-0.2.0}/gofeatureflag_python_provider/request_flag_evaluation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gofeatureflag-python-provider
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: GO Feature Flag provider for OpenFeature
|
|
5
5
|
Home-page: https://gofeatureflag.org
|
|
6
6
|
License: Apache-2.0
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
17
17
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
18
|
Requires-Dist: asyncio (>=3.4.3,<4.0.0)
|
|
19
|
-
Requires-Dist: openfeature-sdk (>=0.
|
|
19
|
+
Requires-Dist: openfeature-sdk (>=0.5.0,<0.8.0)
|
|
20
20
|
Requires-Dist: pydantic (>=2.5.2,<3.0.0)
|
|
21
21
|
Requires-Dist: pylru (>=1.2.1,<2.0.0)
|
|
22
22
|
Requires-Dist: rel (>=0.4.9,<0.5.0)
|
|
@@ -58,13 +58,13 @@ from gofeatureflag_python_provider.options import GoFeatureFlagOptions
|
|
|
58
58
|
from openfeature import api
|
|
59
59
|
from openfeature.evaluation_context import EvaluationContext
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
# ...
|
|
62
62
|
|
|
63
63
|
goff_provider = GoFeatureFlagProvider(
|
|
64
64
|
options=GoFeatureFlagOptions(endpoint="https://gofeatureflag.org/")
|
|
65
65
|
)
|
|
66
66
|
api.set_provider(goff_provider)
|
|
67
|
-
client = api.get_client(
|
|
67
|
+
client = api.get_client(domain="test-client")
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
## Evaluate your flag
|
|
@@ -76,9 +76,9 @@ This code block explains how you can create an `EvaluationContext` and use it to
|
|
|
76
76
|
>
|
|
77
77
|
> **Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.**
|
|
78
78
|
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
```python
|
|
80
|
+
# Context of your flag evaluation.
|
|
81
|
+
# With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user.
|
|
82
82
|
evaluation_ctx = EvaluationContext(
|
|
83
83
|
targeting_key="d45e303a-38c2-11ed-a261-0242ac120002",
|
|
84
84
|
attributes={
|
|
@@ -28,13 +28,13 @@ from gofeatureflag_python_provider.options import GoFeatureFlagOptions
|
|
|
28
28
|
from openfeature import api
|
|
29
29
|
from openfeature.evaluation_context import EvaluationContext
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
# ...
|
|
32
32
|
|
|
33
33
|
goff_provider = GoFeatureFlagProvider(
|
|
34
34
|
options=GoFeatureFlagOptions(endpoint="https://gofeatureflag.org/")
|
|
35
35
|
)
|
|
36
36
|
api.set_provider(goff_provider)
|
|
37
|
-
client = api.get_client(
|
|
37
|
+
client = api.get_client(domain="test-client")
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## Evaluate your flag
|
|
@@ -46,9 +46,9 @@ This code block explains how you can create an `EvaluationContext` and use it to
|
|
|
46
46
|
>
|
|
47
47
|
> **Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.**
|
|
48
48
|
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
```python
|
|
50
|
+
# Context of your flag evaluation.
|
|
51
|
+
# With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user.
|
|
52
52
|
evaluation_ctx = EvaluationContext(
|
|
53
53
|
targeting_key="d45e303a-38c2-11ed-a261-0242ac120002",
|
|
54
54
|
attributes={
|
|
@@ -8,32 +8,29 @@ import pylru
|
|
|
8
8
|
import urllib3
|
|
9
9
|
import websocket
|
|
10
10
|
from openfeature.evaluation_context import EvaluationContext
|
|
11
|
-
from openfeature.exception import ErrorCode
|
|
12
11
|
from openfeature.exception import (
|
|
12
|
+
ErrorCode,
|
|
13
13
|
FlagNotFoundError,
|
|
14
|
-
TypeMismatchError,
|
|
15
14
|
GeneralError,
|
|
16
15
|
OpenFeatureError,
|
|
16
|
+
TypeMismatchError,
|
|
17
17
|
)
|
|
18
|
-
from openfeature.flag_evaluation import
|
|
19
|
-
from openfeature.flag_evaluation import Reason
|
|
18
|
+
from openfeature.flag_evaluation import FlagResolutionDetails, Reason
|
|
20
19
|
from openfeature.hook import Hook
|
|
21
20
|
from openfeature.provider.metadata import Metadata
|
|
22
|
-
from openfeature.provider
|
|
23
|
-
from pydantic import
|
|
21
|
+
from openfeature.provider import AbstractProvider
|
|
22
|
+
from pydantic import PrivateAttr, ValidationError
|
|
24
23
|
|
|
25
24
|
from gofeatureflag_python_provider.data_collector_hook import DataCollectorHook
|
|
26
25
|
from gofeatureflag_python_provider.metadata import GoFeatureFlagMetadata
|
|
27
|
-
from gofeatureflag_python_provider.options import BaseModel
|
|
28
|
-
from gofeatureflag_python_provider.options import GoFeatureFlagOptions
|
|
29
|
-
from gofeatureflag_python_provider.provider_status import ProviderStatus
|
|
26
|
+
from gofeatureflag_python_provider.options import BaseModel, GoFeatureFlagOptions
|
|
30
27
|
from gofeatureflag_python_provider.request_flag_evaluation import (
|
|
31
28
|
RequestFlagEvaluation,
|
|
32
29
|
convert_evaluation_context,
|
|
33
30
|
)
|
|
34
31
|
from gofeatureflag_python_provider.response_flag_evaluation import (
|
|
35
|
-
ResponseFlagEvaluation,
|
|
36
32
|
JsonType,
|
|
33
|
+
ResponseFlagEvaluation,
|
|
37
34
|
)
|
|
38
35
|
|
|
39
36
|
AbstractProviderMetaclass = type(AbstractProvider)
|
|
@@ -48,7 +45,6 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
48
45
|
options: GoFeatureFlagOptions
|
|
49
46
|
_http_client: urllib3.PoolManager = PrivateAttr()
|
|
50
47
|
_cache: pylru.lrucache = PrivateAttr()
|
|
51
|
-
_status: ProviderStatus = PrivateAttr(ProviderStatus.NOT_READY)
|
|
52
48
|
_data_collector_hook: Optional[DataCollectorHook] = PrivateAttr()
|
|
53
49
|
_ws: websocket.WebSocketApp = PrivateAttr()
|
|
54
50
|
_ws_thread: Thread = PrivateAttr()
|
|
@@ -77,18 +73,8 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
77
73
|
self._ws = websocket.WebSocketApp(
|
|
78
74
|
self._build_websocket_uri(),
|
|
79
75
|
on_message=self._websocket_message_handler,
|
|
80
|
-
on_open=self._websocket_open_handler,
|
|
81
|
-
on_close=self._websocket_close_handler,
|
|
82
|
-
on_error=self._websocket_error_handler,
|
|
83
76
|
)
|
|
84
77
|
|
|
85
|
-
def get_status(self) -> ProviderStatus:
|
|
86
|
-
"""
|
|
87
|
-
get_status returns the status of the provider
|
|
88
|
-
:return: the status of the provider
|
|
89
|
-
"""
|
|
90
|
-
return self._status
|
|
91
|
-
|
|
92
78
|
def initialize(self, evaluation_context: EvaluationContext) -> None:
|
|
93
79
|
"""
|
|
94
80
|
initialize is called when the provider is initialized.
|
|
@@ -101,8 +87,6 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
101
87
|
if self.options.disable_cache_invalidation is False:
|
|
102
88
|
self._ws_thread = Thread(target=self.run_websocket)
|
|
103
89
|
self._ws_thread.start()
|
|
104
|
-
else:
|
|
105
|
-
self._status = ProviderStatus.READY
|
|
106
90
|
|
|
107
91
|
def shutdown(self):
|
|
108
92
|
if self.options.disable_cache_invalidation is False:
|
|
@@ -116,8 +100,6 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
116
100
|
self._data_collector_hook.shutdown()
|
|
117
101
|
self._data_collector_hook = None
|
|
118
102
|
|
|
119
|
-
self._status = ProviderStatus.NOT_READY
|
|
120
|
-
|
|
121
103
|
def get_metadata(self) -> Metadata:
|
|
122
104
|
return GoFeatureFlagMetadata()
|
|
123
105
|
|
|
@@ -131,7 +113,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
131
113
|
flag_key: str,
|
|
132
114
|
default_value: bool,
|
|
133
115
|
evaluation_context: Optional[EvaluationContext] = None,
|
|
134
|
-
) ->
|
|
116
|
+
) -> FlagResolutionDetails[bool]:
|
|
135
117
|
return self.generic_go_feature_flag_resolver(
|
|
136
118
|
bool, flag_key, default_value, evaluation_context
|
|
137
119
|
)
|
|
@@ -141,7 +123,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
141
123
|
flag_key: str,
|
|
142
124
|
default_value: str,
|
|
143
125
|
evaluation_context: Optional[EvaluationContext] = None,
|
|
144
|
-
) ->
|
|
126
|
+
) -> FlagResolutionDetails[str]:
|
|
145
127
|
return self.generic_go_feature_flag_resolver(
|
|
146
128
|
str, flag_key, default_value, evaluation_context
|
|
147
129
|
)
|
|
@@ -151,7 +133,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
151
133
|
flag_key: str,
|
|
152
134
|
default_value: int,
|
|
153
135
|
evaluation_context: Optional[EvaluationContext] = None,
|
|
154
|
-
) ->
|
|
136
|
+
) -> FlagResolutionDetails[int]:
|
|
155
137
|
return self.generic_go_feature_flag_resolver(
|
|
156
138
|
int, flag_key, default_value, evaluation_context
|
|
157
139
|
)
|
|
@@ -161,7 +143,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
161
143
|
flag_key: str,
|
|
162
144
|
default_value: float,
|
|
163
145
|
evaluation_context: Optional[EvaluationContext] = None,
|
|
164
|
-
) ->
|
|
146
|
+
) -> FlagResolutionDetails[float]:
|
|
165
147
|
return self.generic_go_feature_flag_resolver(
|
|
166
148
|
float, flag_key, default_value, evaluation_context
|
|
167
149
|
)
|
|
@@ -171,7 +153,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
171
153
|
flag_key: str,
|
|
172
154
|
default_value: dict,
|
|
173
155
|
evaluation_context: Optional[EvaluationContext] = None,
|
|
174
|
-
) ->
|
|
156
|
+
) -> FlagResolutionDetails[Union[list, dict]]:
|
|
175
157
|
return self.generic_go_feature_flag_resolver(
|
|
176
158
|
Union[dict, list], flag_key, default_value, evaluation_context
|
|
177
159
|
)
|
|
@@ -182,7 +164,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
182
164
|
flag_key: str,
|
|
183
165
|
default_value: JsonType,
|
|
184
166
|
evaluation_context: Optional[EvaluationContext] = None,
|
|
185
|
-
) ->
|
|
167
|
+
) -> FlagResolutionDetails[JsonType]:
|
|
186
168
|
"""
|
|
187
169
|
generic_go_feature_flag_resolver is a generic evaluations of your flag with GO Feature Flag relay proxy it works
|
|
188
170
|
with all types.
|
|
@@ -191,18 +173,9 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
191
173
|
:param flag_key: name of the flag
|
|
192
174
|
:param default_value: default value of the flag
|
|
193
175
|
:param evaluation_context: context to evaluate the flag
|
|
194
|
-
:return: a
|
|
176
|
+
:return: a FlagResolutionDetails object containing the response for the SDK.
|
|
195
177
|
"""
|
|
196
178
|
try:
|
|
197
|
-
if self._status != ProviderStatus.READY:
|
|
198
|
-
return FlagEvaluationDetails[original_type](
|
|
199
|
-
flag_key=flag_key,
|
|
200
|
-
value=default_value,
|
|
201
|
-
reason=Reason.ERROR,
|
|
202
|
-
error_code=ErrorCode.PROVIDER_NOT_READY,
|
|
203
|
-
error_message="GO Feature Flag provider is not ready",
|
|
204
|
-
)
|
|
205
|
-
|
|
206
179
|
goff_evaluation_context = convert_evaluation_context(evaluation_context)
|
|
207
180
|
goff_request = RequestFlagEvaluation(
|
|
208
181
|
user=goff_evaluation_context,
|
|
@@ -252,8 +225,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
252
225
|
)
|
|
253
226
|
|
|
254
227
|
if response_flag_evaluation.reason == Reason.DISABLED.value:
|
|
255
|
-
return
|
|
256
|
-
flag_key=flag_key,
|
|
228
|
+
return FlagResolutionDetails[original_type](
|
|
257
229
|
value=default_value,
|
|
258
230
|
reason=Reason.DISABLED,
|
|
259
231
|
)
|
|
@@ -263,8 +235,7 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
263
235
|
"flag {} was not found in your configuration".format(flag_key)
|
|
264
236
|
)
|
|
265
237
|
|
|
266
|
-
return
|
|
267
|
-
flag_key=flag_key,
|
|
238
|
+
return FlagResolutionDetails[original_type](
|
|
268
239
|
value=response_flag_evaluation.value,
|
|
269
240
|
variant=response_flag_evaluation.variationType,
|
|
270
241
|
reason=(
|
|
@@ -315,29 +286,5 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
|
|
|
315
286
|
# when we receive a message from go-feature-flag server, we clear the cache.
|
|
316
287
|
self._cache.clear()
|
|
317
288
|
|
|
318
|
-
def
|
|
319
|
-
|
|
320
|
-
websocket_open_handler is the handler called when the websocket is open
|
|
321
|
-
:param ws app: the websocket app
|
|
322
|
-
:return: None
|
|
323
|
-
"""
|
|
324
|
-
self._status = ProviderStatus.READY
|
|
325
|
-
|
|
326
|
-
def _websocket_error_handler(self, ws_app, error) -> None:
|
|
327
|
-
"""
|
|
328
|
-
websocket_error_handler is the handler called when we receive an error from the GO Feature Flag server
|
|
329
|
-
:param ws_app: the websocket app
|
|
330
|
-
:param error: error received
|
|
331
|
-
:return: None
|
|
332
|
-
"""
|
|
333
|
-
self._status = ProviderStatus.ERROR
|
|
334
|
-
|
|
335
|
-
def _websocket_close_handler(self, ws_app, close_status_code, close_msg) -> None:
|
|
336
|
-
"""
|
|
337
|
-
websocket_close_handler is the handler called when the websocket is closed
|
|
338
|
-
:param wsapp: the websocket app
|
|
339
|
-
:param close_status_code: the status code of the close
|
|
340
|
-
:param close_msg: the message of the close
|
|
341
|
-
:return: None
|
|
342
|
-
"""
|
|
343
|
-
self._status = ProviderStatus.STALE
|
|
289
|
+
def __hash__(self):
|
|
290
|
+
return id(self)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "gofeatureflag-python-provider"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "GO Feature Flag provider for OpenFeature"
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
authors = [ "Thomas Poignant" ]
|
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
|
28
28
|
|
|
29
29
|
[tool.poetry.dependencies]
|
|
30
30
|
python = "^3.9"
|
|
31
|
-
openfeature-sdk = "
|
|
31
|
+
openfeature-sdk = ">=0.5.0,<0.8.0"
|
|
32
32
|
pydantic = "^2.5.2"
|
|
33
33
|
urllib3 = "^2.1.0"
|
|
34
34
|
pylru = "^1.2.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|