growthbook 1.4.8__tar.gz → 1.4.10__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.
Files changed (27) hide show
  1. {growthbook-1.4.8/growthbook.egg-info → growthbook-1.4.10}/PKG-INFO +1 -1
  2. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/__init__.py +1 -1
  3. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/growthbook.py +36 -4
  4. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/growthbook_client.py +11 -2
  5. {growthbook-1.4.8 → growthbook-1.4.10/growthbook.egg-info}/PKG-INFO +1 -1
  6. {growthbook-1.4.8 → growthbook-1.4.10}/setup.cfg +1 -1
  7. {growthbook-1.4.8 → growthbook-1.4.10}/LICENSE +0 -0
  8. {growthbook-1.4.8 → growthbook-1.4.10}/MANIFEST.in +0 -0
  9. {growthbook-1.4.8 → growthbook-1.4.10}/README.md +0 -0
  10. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/common_types.py +0 -0
  11. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/core.py +0 -0
  12. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/plugins/__init__.py +0 -0
  13. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/plugins/base.py +0 -0
  14. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/plugins/growthbook_tracking.py +0 -0
  15. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/plugins/request_context.py +0 -0
  16. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook/py.typed +0 -0
  17. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook.egg-info/SOURCES.txt +0 -0
  18. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook.egg-info/dependency_links.txt +0 -0
  19. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook.egg-info/requires.txt +0 -0
  20. {growthbook-1.4.8 → growthbook-1.4.10}/growthbook.egg-info/top_level.txt +0 -0
  21. {growthbook-1.4.8 → growthbook-1.4.10}/pyproject.toml +0 -0
  22. {growthbook-1.4.8 → growthbook-1.4.10}/setup.py +0 -0
  23. {growthbook-1.4.8 → growthbook-1.4.10}/tests/conftest.py +0 -0
  24. {growthbook-1.4.8 → growthbook-1.4.10}/tests/test_etag.py +0 -0
  25. {growthbook-1.4.8 → growthbook-1.4.10}/tests/test_growthbook.py +0 -0
  26. {growthbook-1.4.8 → growthbook-1.4.10}/tests/test_growthbook_client.py +0 -0
  27. {growthbook-1.4.8 → growthbook-1.4.10}/tests/test_plugins.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: growthbook
3
- Version: 1.4.8
3
+ Version: 1.4.10
4
4
  Summary: Powerful Feature flagging and A/B testing for Python apps
5
5
  Home-page: https://github.com/growthbook/growthbook-python
6
6
  Author: GrowthBook
@@ -18,5 +18,5 @@ from .plugins import (
18
18
  )
19
19
 
20
20
  # x-release-please-start-version
21
- __version__ = "1.4.8"
21
+ __version__ = "1.4.10"
22
22
  # x-release-please-end
@@ -139,6 +139,7 @@ class SSEClient:
139
139
  self.headers = {
140
140
  "Accept": "application/json; q=0.5, text/event-stream",
141
141
  "Cache-Control": "no-cache",
142
+ "Accept-Encoding": "gzip, deflate, br",
142
143
  }
143
144
 
144
145
  if headers:
@@ -408,15 +409,35 @@ class FeatureRepository(object):
408
409
  self._notify_feature_update_callbacks(res)
409
410
  return res
410
411
  return cached
412
+
413
+ @property
414
+ def user_agent_suffix(self) -> Optional[str]:
415
+ return getattr(self, "_user_agent_suffix", None)
416
+
417
+ @user_agent_suffix.setter
418
+ def user_agent_suffix(self, value: Optional[str]) -> None:
419
+ self._user_agent_suffix = value
411
420
 
412
421
  # Perform the GET request (separate method for easy mocking)
413
422
  def _get(self, url: str, headers: Optional[Dict[str, str]] = None):
414
423
  self.http = self.http or PoolManager()
415
424
  return self.http.request("GET", url, headers=headers or {})
425
+
426
+ def _get_headers(self, client_key: str, existing_headers: Dict[str, str] = None) -> Dict[str, str]:
427
+ headers = existing_headers or {}
428
+ headers['Accept-Encoding'] = "gzip, deflate"
429
+
430
+ # Add User-Agent with optional suffix
431
+ ua = "Gb-Python"
432
+ ua += f"-{self.user_agent_suffix}" if self.user_agent_suffix else f"-{client_key[-4:]}"
433
+ headers['User-Agent'] = ua
434
+
435
+ return headers
416
436
 
417
437
  def _fetch_and_decode(self, api_host: str, client_key: str) -> Optional[Dict]:
418
438
  url = self._get_features_url(api_host, client_key)
419
- headers: Dict[str, str] = {}
439
+ headers = self._get_headers(client_key)
440
+ logger.debug(f"Fetching features from {url} with headers {headers}")
420
441
 
421
442
  # Check if we have a cached ETag for this URL
422
443
  cached_etag = None
@@ -471,12 +492,13 @@ class FeatureRepository(object):
471
492
 
472
493
  return decoded # type: ignore[no-any-return]
473
494
  except Exception as e:
474
- logger.warning(f"Failed to decode feature JSON from GrowthBook API: {e}")
495
+ logger.error(f"Failed to decode feature JSON from GrowthBook API: {e}")
475
496
  return None
476
497
 
477
498
  async def _fetch_and_decode_async(self, api_host: str, client_key: str) -> Optional[Dict]:
478
499
  url = self._get_features_url(api_host, client_key)
479
- headers: Dict[str, str] = {}
500
+ headers = self._get_headers(client_key=client_key)
501
+ logger.debug(f"[Async] Fetching features from {url} with headers {headers}")
480
502
 
481
503
  # Check if we have a cached ETag for this URL
482
504
  cached_etag = None
@@ -532,7 +554,7 @@ class FeatureRepository(object):
532
554
  logger.warning(f"HTTP request failed: {e}")
533
555
  return None
534
556
  except Exception as e:
535
- logger.warning("Failed to decode feature JSON from GrowthBook API: %s", e)
557
+ logger.error(f"Failed to decode feature JSON from GrowthBook API: {e}")
536
558
  return None
537
559
 
538
560
  def decrypt_response(self, data, decryption_key: str):
@@ -1131,6 +1153,16 @@ class GrowthBook(object):
1131
1153
  except Exception as e:
1132
1154
  logger.error(f"Failed to initialize plugin {plugin}: {e}")
1133
1155
 
1156
+ @property
1157
+ def user_agent_suffix(self) -> Optional[str]:
1158
+ """Get the suffix appended to the User-Agent header"""
1159
+ return feature_repo.user_agent_suffix
1160
+
1161
+ @user_agent_suffix.setter
1162
+ def user_agent_suffix(self, value: Optional[str]) -> None:
1163
+ """Set a suffix to be appended to the User-Agent header"""
1164
+ feature_repo.user_agent_suffix = value
1165
+
1134
1166
  def _cleanup_plugins(self) -> None:
1135
1167
  """Cleanup all initialized plugins."""
1136
1168
  for plugin in self._initialized_plugins:
@@ -9,7 +9,7 @@ import asyncio
9
9
  import threading
10
10
  import traceback
11
11
  from datetime import datetime
12
- from growthbook import FeatureRepository
12
+ from growthbook import FeatureRepository, feature_repo
13
13
  from contextlib import asynccontextmanager
14
14
 
15
15
  from .core import eval_feature as core_eval_feature, run_experiment
@@ -569,7 +569,6 @@ class GrowthBookClient:
569
569
  self._tracked.clear()
570
570
  with self._subscriptions_lock:
571
571
  self._subscriptions.clear()
572
-
573
572
  # Clear context
574
573
  async with self._context_lock:
575
574
  self._global_context = None
@@ -577,6 +576,16 @@ class GrowthBookClient:
577
576
  # Cleanup plugins
578
577
  self._cleanup_plugins()
579
578
 
579
+ @property
580
+ def user_agent_suffix(self) -> Optional[str]:
581
+ """Get the suffix appended to the User-Agent header"""
582
+ return feature_repo.user_agent_suffix
583
+
584
+ @user_agent_suffix.setter
585
+ def user_agent_suffix(self, value: Optional[str]) -> None:
586
+ """Set a suffix to be appended to the User-Agent header"""
587
+ feature_repo.user_agent_suffix = value
588
+
580
589
  def _initialize_plugins(self) -> None:
581
590
  """Initialize all tracking plugins with this GrowthBookClient instance."""
582
591
  for plugin in self._tracking_plugins:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: growthbook
3
- Version: 1.4.8
3
+ Version: 1.4.10
4
4
  Summary: Powerful Feature flagging and A/B testing for Python apps
5
5
  Home-page: https://github.com/growthbook/growthbook-python
6
6
  Author: GrowthBook
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 1.4.8
2
+ current_version = 1.4.10
3
3
  commit = True
4
4
  tag = True
5
5
 
File without changes
File without changes
File without changes
File without changes
File without changes