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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gofeatureflag-python-provider
3
- Version: 0.1.1
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.4.1,<0.5.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(name="test-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
- ```csharp
80
- // Context of your flag evaluation.
81
- // With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user.
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(name="test-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
- ```csharp
50
- // Context of your flag evaluation.
51
- // With GO Feature Flag you MUST have a targetingKey that is a unique identifier of the user.
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 FlagEvaluationDetails
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.provider import AbstractProvider
23
- from pydantic import ValidationError, PrivateAttr
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
- ) -> FlagEvaluationDetails[bool]:
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
- ) -> FlagEvaluationDetails[str]:
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
- ) -> FlagEvaluationDetails[int]:
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
- ) -> FlagEvaluationDetails[float]:
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
- ) -> FlagEvaluationDetails[Union[list, dict]]:
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
- ) -> FlagEvaluationDetails[JsonType]:
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 FlagEvaluationDetails object containing the response for the SDK.
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 FlagEvaluationDetails[original_type](
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 FlagEvaluationDetails[original_type](
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 _websocket_open_handler(self, ws_app) -> None:
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,4 +1,4 @@
1
- from typing import Optional, Generic, Union, TypeVar
1
+ from typing import Optional, Union, TypeVar
2
2
  from gofeatureflag_python_provider.options import BaseModel
3
3
 
4
4
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "gofeatureflag-python-provider"
3
- version = "0.1.1"
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 = "^0.4.1"
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"
@@ -1,9 +0,0 @@
1
- from enum import Enum
2
-
3
-
4
- # ProviderStatus is an enum that represents the status of a provider
5
- class ProviderStatus(Enum):
6
- NOT_READY = 1
7
- READY = 2
8
- STALE = 3
9
- ERROR = 4