gofeatureflag-python-provider 0.2.1__tar.gz → 0.4.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,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: gofeatureflag-python-provider
3
- Version: 0.2.1
3
+ Version: 0.4.0
4
4
  Summary: GO Feature Flag provider for OpenFeature
5
- Home-page: https://gofeatureflag.org
6
5
  License: Apache-2.0
7
6
  Keywords: feature flags,feature toggles,go-feature-flag,gofeatureflag,openfeature,open-feature
8
7
  Author: Thomas Poignant
@@ -13,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.9
13
12
  Classifier: Programming Language :: Python :: 3.10
14
13
  Classifier: Programming Language :: Python :: 3.11
15
14
  Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
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)
@@ -24,6 +24,7 @@ Requires-Dist: urllib3 (>=2.1.0,<3.0.0)
24
24
  Requires-Dist: websocket-client (>=1.6.4,<2.0.0)
25
25
  Project-URL: Bug Tracker, https://github.com/thomaspoignant/go-feature-flag/issues
26
26
  Project-URL: Documentation, https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider
27
+ Project-URL: Homepage, https://gofeatureflag.org
27
28
  Project-URL: Repository, https://github.com/thomaspoignant/go-feature-flag
28
29
  Project-URL: Source Code, https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider
29
30
  Description-Content-Type: text/markdown
@@ -1,19 +1,17 @@
1
1
  import datetime
2
2
  import threading
3
3
  import time
4
- from http import HTTPStatus
5
- from typing import Optional
6
- from urllib.parse import urljoin
7
-
8
4
  import urllib3
9
- from openfeature.flag_evaluation import FlagEvaluationDetails, Reason
10
- from openfeature.hook import Hook, HookContext
11
-
12
5
  from gofeatureflag_python_provider.options import GoFeatureFlagOptions
13
6
  from gofeatureflag_python_provider.request_data_collector import (
14
7
  FeatureEvent,
15
8
  RequestDataCollector,
16
9
  )
10
+ from http import HTTPStatus
11
+ from openfeature.flag_evaluation import FlagEvaluationDetails, Reason
12
+ from openfeature.hook import Hook, HookContext
13
+ from typing import Optional
14
+ from urllib.parse import urljoin
17
15
 
18
16
  default_targeting_key = "undefined-targetingKey"
19
17
 
@@ -31,6 +29,8 @@ class DataCollectorHook(Hook):
31
29
  _http_client: urllib3.PoolManager = None
32
30
  # _data_event_queue is the list of data to collect
33
31
  _event_queue: list[FeatureEvent] = []
32
+ # _exporter_metadata is the metadata we send to the GO Feature Flag relay proxy when we report the evaluation data usage.
33
+ _exporter_metadata: dict = {}
34
34
 
35
35
  def __init__(self, options: GoFeatureFlagOptions, http_client: urllib3.PoolManager):
36
36
  self._http_client = http_client
@@ -39,6 +39,9 @@ class DataCollectorHook(Hook):
39
39
  self._data_collector_endpoint = urljoin(
40
40
  str(self._options.endpoint), "/v1/data/collector"
41
41
  )
42
+ self._exporter_metadata = options.exporter_metadata
43
+ self._exporter_metadata["provider"] = "python"
44
+ self._exporter_metadata["openfeature"] = True
42
45
 
43
46
  def after(
44
47
  self, hook_context: HookContext, details: FlagEvaluationDetails, hints: dict
@@ -106,13 +109,17 @@ class DataCollectorHook(Hook):
106
109
  if len(self._event_queue) > 0:
107
110
  try:
108
111
  goff_request = RequestDataCollector(
109
- meta={"provider": "open-feature-python-sdk"},
112
+ meta=self._exporter_metadata,
110
113
  events=self._event_queue,
111
114
  )
115
+ headers = {"Content-Type": "application/json"}
116
+ if self._options.api_key:
117
+ headers["Authorization"] = "Bearer {}".format(self._options.api_key)
118
+
112
119
  response = self._http_client.request(
113
120
  method="POST",
114
121
  url=urljoin(str(self._options.endpoint), "/v1/data/collector"),
115
- headers={"Content-Type": "application/json"},
122
+ headers=headers,
116
123
  body=goff_request.model_dump_json(),
117
124
  )
118
125
 
@@ -45,3 +45,15 @@ class GoFeatureFlagOptions(BaseModel):
45
45
  # config changes.
46
46
  # default: false
47
47
  disable_cache_invalidation: typing.Optional[bool] = False
48
+
49
+ # api_key (optional) If the relay proxy is configured to authenticate the requests, you should provide
50
+ # an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key.
51
+ # Default: None
52
+ api_key: typing.Optional[str] = None
53
+
54
+ # ExporterMetadata (optional) is the metadata we send to the GO Feature Flag relay proxy when we report the
55
+ # evaluation data usage.
56
+ #
57
+ # ‼️Important: If you are using a GO Feature Flag relay proxy before version v1.41.0, the information of this
58
+ # field will not be added to your feature events.
59
+ exporter_metadata: typing.Optional[dict] = {}
@@ -188,13 +188,18 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
188
188
  response_body = self._cache[evaluation_context_hash]
189
189
  is_from_cache = True
190
190
  else:
191
+ headers = {"Content-Type": "application/json"}
192
+ if self.options.api_key is not None:
193
+ headers["Authorization"] = "Bearer {}".format(self.options.api_key)
194
+ url = "{}{}".format(
195
+ str(self.options.endpoint).rstrip("/"),
196
+ "/v1/feature/{}/eval".format(flag_key),
197
+ )
198
+
191
199
  response = self._http_client.request(
192
200
  method="POST",
193
- url=urljoin(
194
- str(self.options.endpoint),
195
- "/v1/feature/{}/eval".format(flag_key),
196
- ),
197
- headers={"Content-Type": "application/json"},
201
+ url=url,
202
+ headers=headers,
198
203
  body=goff_request.model_dump_json(),
199
204
  )
200
205
 
@@ -261,10 +266,15 @@ class GoFeatureFlagProvider(BaseModel, AbstractProvider, metaclass=CombinedMetac
261
266
  _build_websocket_uri is a helper to build the websocket uri to connect to the GO Feature Flag relay proxy.
262
267
  :return: a string representing the websocket uri
263
268
  """
264
- http_uri = urljoin(
265
- str(self.options.endpoint),
266
- "/ws/v1/flag/change",
269
+ url = "/ws/v1/flag/change"
270
+ if self.options.api_key is not None:
271
+ url = "{}?apiKey={}".format(url, self.options.api_key)
272
+
273
+ http_uri = "{}{}".format(
274
+ str(self.options.endpoint).rstrip("/"),
275
+ url,
267
276
  )
277
+
268
278
  http_uri = http_uri.replace("http", "ws")
269
279
  http_uri = http_uri.replace("https", "wss")
270
280
  return http_uri
@@ -1,8 +1,6 @@
1
- from typing import Optional, Any
2
-
3
- from pydantic import Field, SkipValidation
4
-
5
1
  from gofeatureflag_python_provider.options import BaseModel
2
+ from pydantic import Field, SkipValidation
3
+ from typing import Optional, Any, Union
6
4
 
7
5
 
8
6
  class FeatureEvent(BaseModel):
@@ -47,7 +45,7 @@ class FeatureEvent(BaseModel):
47
45
 
48
46
  class RequestDataCollector(BaseModel):
49
47
  # Meta are the extra information added to identify who is calling the endpoint.
50
- meta: Optional[dict[str, str]] = None
48
+ meta: Optional[dict[str, Union[str, int, float, bool]]] = None
51
49
 
52
50
  # Events is the list of the event we send in the payload
53
51
  events: list[FeatureEvent] = []
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "gofeatureflag-python-provider"
3
- version = "0.2.1"
3
+ version = "0.4.0"
4
4
  description = "GO Feature Flag provider for OpenFeature"
5
5
  license = "Apache-2.0"
6
6
  authors = [ "Thomas Poignant" ]