kameleoon-client-python 3.3.2__tar.gz → 3.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.
Files changed (172) hide show
  1. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/PKG-INFO +3 -3
  2. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/README.md +2 -2
  3. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/__init__.py +1 -0
  4. kameleoon-client-python-3.4.0/kameleoon/client_readiness/async_readiness.py +48 -0
  5. kameleoon-client-python-3.4.0/kameleoon/client_readiness/threading_readiness.py +44 -0
  6. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/custom_data_info.py +5 -4
  7. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/data_file.py +23 -5
  8. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/feature_flag.py +13 -0
  9. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/rule.py +3 -0
  10. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/settings.py +7 -0
  11. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/variable.py +7 -0
  12. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/variation.py +5 -0
  13. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/variation_by_exposition.py +7 -0
  14. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/__init__.py +14 -12
  15. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/browser.py +9 -3
  16. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/conversion.py +9 -2
  17. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/cookie.py +3 -0
  18. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/custom_data.py +11 -8
  19. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/data.py +2 -1
  20. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/device.py +5 -2
  21. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/geolocation.py +18 -8
  22. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/kcs_heat.py +3 -0
  23. kameleoon-client-python-3.4.0/kameleoon/data/manager/assigned_variation.py +71 -0
  24. kameleoon-client-python-3.4.0/kameleoon/data/manager/page_view_visit.py +44 -0
  25. kameleoon-client-python-3.4.0/kameleoon/data/manager/visitor.py +371 -0
  26. kameleoon-client-python-3.4.0/kameleoon/data/manager/visitor_manager.py +149 -0
  27. kameleoon-client-python-3.4.0/kameleoon/data/manager/visitor_slot.py +18 -0
  28. kameleoon-client-python-3.4.0/kameleoon/data/mapping_identifier.py +25 -0
  29. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/operating_system.py +5 -2
  30. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/page_view.py +11 -4
  31. kameleoon-client-python-3.4.0/kameleoon/data/unique_identifier.py +12 -0
  32. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/user_agent.py +3 -0
  33. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/data/visitor_visits.py +3 -0
  34. kameleoon-client-python-3.4.0/kameleoon/helpers/domain.py +42 -0
  35. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/helpers/multi_threading.py +39 -24
  36. kameleoon-client-python-3.4.0/kameleoon/helpers/repeat_timer.py +12 -0
  37. kameleoon-client-python-3.4.0/kameleoon/helpers/scheduler.py +95 -0
  38. kameleoon-client-python-3.4.0/kameleoon/helpers/string_utils.py +51 -0
  39. kameleoon-client-python-3.4.0/kameleoon/hybrid/hybrid_manager.py +10 -0
  40. kameleoon-client-python-3.4.0/kameleoon/hybrid/hybrid_manager_impl.py +36 -0
  41. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/kameleoon_client.py +387 -296
  42. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/kameleoon_client_config.py +77 -24
  43. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/kameleoon_client_factory.py +21 -10
  44. kameleoon-client-python-3.4.0/kameleoon/logging/kameleoon_logger.py +70 -0
  45. kameleoon-client-python-3.4.0/kameleoon/logging/log_level.py +11 -0
  46. kameleoon-client-python-3.4.0/kameleoon/logging/logger.py +36 -0
  47. kameleoon-client-python-3.4.0/kameleoon/managers/asyncexec/async_executor.py +80 -0
  48. kameleoon-client-python-3.4.0/kameleoon/managers/data/data_manager.py +42 -0
  49. kameleoon-client-python-3.4.0/kameleoon/managers/remote_data/remote_data_manager.py +85 -0
  50. kameleoon-client-python-3.4.0/kameleoon/managers/remote_data/remote_visitor_data.py +230 -0
  51. kameleoon-client-python-3.4.0/kameleoon/managers/tracking/__init__.py +0 -0
  52. kameleoon-client-python-3.4.0/kameleoon/managers/tracking/tracking_builder.py +153 -0
  53. kameleoon-client-python-3.4.0/kameleoon/managers/tracking/tracking_manager.py +107 -0
  54. kameleoon-client-python-3.4.0/kameleoon/managers/tracking/visitor_tracking_registry.py +89 -0
  55. kameleoon-client-python-3.4.0/kameleoon/managers/warehouse/__init__.py +0 -0
  56. kameleoon-client-python-3.4.0/kameleoon/managers/warehouse/warehouse_manager.py +66 -0
  57. kameleoon-client-python-3.4.0/kameleoon/network/__init__.py +0 -0
  58. kameleoon-client-python-3.4.0/kameleoon/network/access_token_source.py +130 -0
  59. kameleoon-client-python-3.4.0/kameleoon/network/access_token_source_factory.py +16 -0
  60. kameleoon-client-python-3.4.0/kameleoon/network/activity_event.py +11 -0
  61. kameleoon-client-python-3.4.0/kameleoon/network/cookie/__init__.py +0 -0
  62. kameleoon-client-python-3.4.0/kameleoon/network/cookie/cookie_manager.py +107 -0
  63. kameleoon-client-python-3.4.0/kameleoon/network/net_provider.py +75 -0
  64. kameleoon-client-python-3.4.0/kameleoon/network/net_provider_impl.py +79 -0
  65. kameleoon-client-python-3.4.0/kameleoon/network/network_manager.py +46 -0
  66. kameleoon-client-python-3.4.0/kameleoon/network/network_manager_factory.py +20 -0
  67. kameleoon-client-python-3.4.0/kameleoon/network/network_manager_factory_impl.py +42 -0
  68. kameleoon-client-python-3.4.0/kameleoon/network/network_manager_impl.py +56 -0
  69. kameleoon-client-python-3.4.0/kameleoon/network/query_builder.py +93 -0
  70. kameleoon-client-python-3.4.0/kameleoon/network/query_encodable.py +8 -0
  71. kameleoon-client-python-3.4.0/kameleoon/network/sendable.py +83 -0
  72. kameleoon-client-python-3.4.0/kameleoon/network/service_initialize_context.py +10 -0
  73. kameleoon-client-python-3.4.0/kameleoon/network/service_initialize_context_impl.py +14 -0
  74. kameleoon-client-python-3.4.0/kameleoon/network/services/__init__.py +0 -0
  75. kameleoon-client-python-3.4.0/kameleoon/network/services/automation_service.py +13 -0
  76. kameleoon-client-python-3.4.0/kameleoon/network/services/automation_service_impl.py +48 -0
  77. kameleoon-client-python-3.4.0/kameleoon/network/services/configuration_service.py +13 -0
  78. kameleoon-client-python-3.4.0/kameleoon/network/services/configuration_service_impl.py +44 -0
  79. kameleoon-client-python-3.4.0/kameleoon/network/services/data_service.py +26 -0
  80. kameleoon-client-python-3.4.0/kameleoon/network/services/data_service_impl.py +75 -0
  81. kameleoon-client-python-3.4.0/kameleoon/network/services/service.py +9 -0
  82. kameleoon-client-python-3.4.0/kameleoon/network/services/service_impl.py +66 -0
  83. kameleoon-client-python-3.4.0/kameleoon/network/uri_helper.py +7 -0
  84. kameleoon-client-python-3.4.0/kameleoon/network/url_provider.py +115 -0
  85. kameleoon-client-python-3.4.0/kameleoon/real_time/__init__.py +0 -0
  86. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/real_time/real_time_configuration_service.py +7 -8
  87. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/sdk_version.py +3 -2
  88. kameleoon-client-python-3.4.0/kameleoon/storage/__init__.py +0 -0
  89. kameleoon-client-python-3.4.0/kameleoon/targeting/__init__.py +0 -0
  90. kameleoon-client-python-3.4.0/kameleoon/targeting/conditions/__init__.py +0 -0
  91. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/browser_condition.py +3 -2
  92. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/conversion_condition.py +2 -1
  93. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/cookie_condition.py +4 -3
  94. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/custom_datum.py +3 -2
  95. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/device_condition.py +2 -1
  96. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/geolocation_condition.py +2 -1
  97. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/number_condition.py +4 -2
  98. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/operating_system_condition.py +2 -1
  99. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/sdk_language_condition.py +4 -2
  100. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/segment_condition.py +2 -1
  101. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/string_value_condition.py +4 -2
  102. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +2 -1
  103. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/targeting_condition.py +0 -7
  104. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +2 -1
  105. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/targeting_manager.py +48 -32
  106. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/tree_builder.py +8 -1
  107. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/tree_condition_factory.py +2 -2
  108. kameleoon-client-python-3.4.0/kameleoon/types/__init__.py +0 -0
  109. kameleoon-client-python-3.4.0/kameleoon/types/remote_visitor_data_filter.py +95 -0
  110. kameleoon-client-python-3.4.0/kameleoon/types/variable.py +33 -0
  111. kameleoon-client-python-3.4.0/kameleoon/types/variation.py +41 -0
  112. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon_client_python.egg-info/PKG-INFO +3 -3
  113. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon_client_python.egg-info/SOURCES.txt +66 -0
  114. kameleoon-client-python-3.4.0/tests/integration/proj/__init__.py +0 -0
  115. kameleoon-client-python-3.4.0/tests/integration/proj/kameleoon_app/__init__.py +0 -0
  116. kameleoon-client-python-3.4.0/tests/integration/proj/kameleoon_app/migrations/__init__.py +0 -0
  117. kameleoon-client-python-3.4.0/tests/integration/proj/proj/__init__.py +0 -0
  118. kameleoon-client-python-3.3.2/kameleoon/helpers/repeat_timer.py +0 -12
  119. kameleoon-client-python-3.3.2/kameleoon/helpers/scheduler.py +0 -67
  120. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/MANIFEST.in +0 -0
  121. {kameleoon-client-python-3.3.2/kameleoon/helpers → kameleoon-client-python-3.4.0/kameleoon/client_readiness}/__init__.py +0 -0
  122. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/__init__.py +0 -0
  123. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/configuration/rule_type.py +0 -0
  124. {kameleoon-client-python-3.3.2/kameleoon/real_time → kameleoon-client-python-3.4.0/kameleoon/data/manager}/__init__.py +0 -0
  125. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/defaults.py +0 -0
  126. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/exceptions.py +0 -0
  127. {kameleoon-client-python-3.3.2/kameleoon/storage → kameleoon-client-python-3.4.0/kameleoon/helpers}/__init__.py +0 -0
  128. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/helpers/functions.py +0 -0
  129. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/helpers/logger.py +0 -0
  130. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/helpers/nonce.py +0 -0
  131. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/helpers/visitor_code.py +0 -0
  132. {kameleoon-client-python-3.3.2/kameleoon/targeting → kameleoon-client-python-3.4.0/kameleoon/hybrid}/__init__.py +0 -0
  133. {kameleoon-client-python-3.3.2/kameleoon/targeting/conditions → kameleoon-client-python-3.4.0/kameleoon/logging}/__init__.py +0 -0
  134. {kameleoon-client-python-3.3.2/tests/integration/proj → kameleoon-client-python-3.4.0/kameleoon/managers}/__init__.py +0 -0
  135. {kameleoon-client-python-3.3.2/tests/integration/proj/kameleoon_app → kameleoon-client-python-3.4.0/kameleoon/managers/asyncexec}/__init__.py +0 -0
  136. {kameleoon-client-python-3.3.2/tests/integration/proj/kameleoon_app/migrations → kameleoon-client-python-3.4.0/kameleoon/managers/data}/__init__.py +0 -0
  137. {kameleoon-client-python-3.3.2/tests/integration/proj/proj → kameleoon-client-python-3.4.0/kameleoon/managers/remote_data}/__init__.py +0 -0
  138. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/middleware.py +0 -0
  139. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/real_time/real_time_event.py +0 -0
  140. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/storage/cache.py +0 -0
  141. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/storage/cache_factory.py +0 -0
  142. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/storage/cache_factory_impl.py +0 -0
  143. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/storage/cache_impl.py +0 -0
  144. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/constants.py +0 -0
  145. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/exclusive_feature_flag_condition.py +0 -0
  146. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
  147. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/page_title_condition.py +0 -0
  148. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/page_url_condition.py +0 -0
  149. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
  150. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
  151. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +0 -0
  152. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/unknown_condition.py +0 -0
  153. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +0 -0
  154. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
  155. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
  156. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon/targeting/models.py +0 -0
  157. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
  158. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon_client_python.egg-info/requires.txt +13 -13
  159. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
  160. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/setup.cfg +0 -0
  161. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/setup.py +0 -0
  162. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
  163. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
  164. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
  165. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
  166. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
  167. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/manage.py +0 -0
  168. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/proj/asgi.py +0 -0
  169. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/proj/settings.py +0 -0
  170. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/proj/urls.py +0 -0
  171. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/integration/proj/proj/wsgi.py +0 -0
  172. {kameleoon-client-python-3.3.2 → kameleoon-client-python-3.4.0}/tests/resources/config.yml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kameleoon-client-python
3
- Version: 3.3.2
3
+ Version: 3.4.0
4
4
  Summary: Kameleoon Client Python Software Development Kit.
5
5
  Home-page: https://developers.kameleoon.com/python-sdk.html
6
6
  Author: Kameleoon
@@ -70,7 +70,7 @@ kameleoon_client = KameleoonClientFactory.create(SITE_CODE, config_path='/etc/ka
70
70
 
71
71
  # Option 2
72
72
  configuration_object = KameleoonClientConfig.read_from_yaml('/etc/kameleoon/client-python.yaml')
73
- configuration_object.set_logger(my_logger)
73
+ configuration_object.set_logger(my_logger) # (is deprecated) use `KameleoonLogger.set_logger` method instead.
74
74
  kameleoon_client = KameleoonClientFactory.create(SITE_CODE, configuration_object)
75
75
 
76
76
  # Option 3
@@ -83,7 +83,7 @@ configuration_object = KameleoonClientConfig(
83
83
  environment="production", # optional, possible values: "production" / "staging" / "development" / "staging", default: None
84
84
  top_level_domain="example.com",
85
85
  multi_threading=False, # optional, default: False
86
- logger=my_logger, # optional, default: standard kameleoon logger
86
+ logger=my_logger, # optional, default: standard kameleoon logger (is deprecated) use `KameleoonLogger.set_logger` method instead.
87
87
  )
88
88
  kameleoon_client = KameleoonClientFactory.create(SITE_CODE, configuration_object)
89
89
  ```
@@ -49,7 +49,7 @@ kameleoon_client = KameleoonClientFactory.create(SITE_CODE, config_path='/etc/ka
49
49
 
50
50
  # Option 2
51
51
  configuration_object = KameleoonClientConfig.read_from_yaml('/etc/kameleoon/client-python.yaml')
52
- configuration_object.set_logger(my_logger)
52
+ configuration_object.set_logger(my_logger) # (is deprecated) use `KameleoonLogger.set_logger` method instead.
53
53
  kameleoon_client = KameleoonClientFactory.create(SITE_CODE, configuration_object)
54
54
 
55
55
  # Option 3
@@ -62,7 +62,7 @@ configuration_object = KameleoonClientConfig(
62
62
  environment="production", # optional, possible values: "production" / "staging" / "development" / "staging", default: None
63
63
  top_level_domain="example.com",
64
64
  multi_threading=False, # optional, default: False
65
- logger=my_logger, # optional, default: standard kameleoon logger
65
+ logger=my_logger, # optional, default: standard kameleoon logger (is deprecated) use `KameleoonLogger.set_logger` method instead.
66
66
  )
67
67
  kameleoon_client = KameleoonClientFactory.create(SITE_CODE, configuration_object)
68
68
  ```
@@ -3,4 +3,5 @@
3
3
  from .sdk_version import __version__ # noqa: F401
4
4
  from .kameleoon_client import KameleoonClient # noqa: F401
5
5
  from .kameleoon_client_config import KameleoonClientConfig # noqa: F401
6
+ from .kameleoon_client_factory import KameleoonClientFactory # noqa: F401
6
7
  from .middleware import KameleoonWSGIMiddleware # noqa: F401
@@ -0,0 +1,48 @@
1
+ "Async Client Readiness"
2
+
3
+ import asyncio
4
+ from concurrent.futures import ThreadPoolExecutor
5
+ from collections import defaultdict
6
+ from typing import Dict
7
+ from kameleoon.client_readiness.threading_readiness import ThreadingClientReadiness
8
+
9
+
10
+ class AsyncClientReadiness:
11
+ """
12
+ A class that provides an asynchronous interface for checking client readiness.
13
+
14
+ This class wraps around a `ThreadingClientReadiness` object to provide asynchronous
15
+ methods for waiting for the client to be ready. It uses a thread pool executor to
16
+ run blocking operations in a separate thread.
17
+ """
18
+
19
+ def __init__(self, inner: ThreadingClientReadiness) -> None:
20
+ """
21
+ Initializes an AsyncClientReadiness instance.
22
+ """
23
+ super().__init__()
24
+ self._inner = inner
25
+ self._executor: Dict[int, ThreadPoolExecutor] = defaultdict(ThreadPoolExecutor)
26
+
27
+ @property
28
+ def inner(self) -> ThreadingClientReadiness:
29
+ """
30
+ Returns the inner ThreadingClientReadiness instance.
31
+ """
32
+ return self._inner
33
+
34
+ def dispose_on_set(self) -> None:
35
+ """
36
+ Disposes of the executors by clearing the executor dictionary.
37
+ """
38
+ self._executor.clear()
39
+
40
+ async def wait(self) -> bool:
41
+ """
42
+ Asynchronously waits for the client readiness operation to complete.
43
+ """
44
+ if self._inner.is_initializing:
45
+ executor = self._executor[0]
46
+ loop = asyncio.get_event_loop()
47
+ await loop.run_in_executor(executor, self._inner.wait)
48
+ return self._inner.success
@@ -0,0 +1,44 @@
1
+ """ThreadingClientReadiness"""
2
+ from threading import Lock
3
+
4
+
5
+ class ThreadingClientReadiness:
6
+ """A class to manage and track the readiness of a component using threading."""
7
+
8
+ def __init__(self) -> None:
9
+ """Initializes the ThreadingClientReadiness object."""
10
+ self._is_initializing = False
11
+ self._success = False
12
+ self._condition = Lock()
13
+ self.reset()
14
+
15
+ @property
16
+ def is_initializing(self) -> bool:
17
+ """Returns whether the component is currently initializing."""
18
+ return self._is_initializing
19
+
20
+ @property
21
+ def success(self) -> bool:
22
+ """Returns whether the initialization was successful."""
23
+ return self._success
24
+
25
+ def reset(self) -> None:
26
+ """Resets the readiness state to initializing."""
27
+ self._success = False
28
+ if not self._is_initializing:
29
+ self._is_initializing = True
30
+ self._condition.acquire() # pylint: disable=R1732
31
+
32
+ def set(self, success: bool) -> None:
33
+ """Sets the readiness state to initialized with a success status."""
34
+ self._success = success
35
+ if self._is_initializing:
36
+ self._condition.release()
37
+ self._is_initializing = False
38
+
39
+ def wait(self) -> bool:
40
+ """Waits for the initialization to complete and returns the success status."""
41
+ if self._is_initializing:
42
+ with self._condition:
43
+ pass
44
+ return self._success
@@ -1,8 +1,9 @@
1
1
  """Custom data info"""
2
2
 
3
- from logging import Logger
4
3
  from typing import Optional, Dict, Union, Any, List
5
4
 
5
+ from kameleoon.logging.kameleoon_logger import KameleoonLogger
6
+
6
7
 
7
8
  class CustomDataInfo:
8
9
  """Custom data info"""
@@ -10,7 +11,7 @@ class CustomDataInfo:
10
11
  SCOPE_VISITOR = "VISITOR"
11
12
 
12
13
  def __init__(
13
- self, custom_data: Optional[List[Dict[str, Union[str, int, Any]]]], logger: Optional[Logger] = None
14
+ self, custom_data: Optional[List[Dict[str, Union[str, int, Any]]]]
14
15
  ) -> None:
15
16
  super().__init__()
16
17
  self.__mapping_identifier_index = None
@@ -26,8 +27,8 @@ class CustomDataInfo:
26
27
  if data.get("scope") == self.SCOPE_VISITOR:
27
28
  self.__visitor_scope.add(index)
28
29
  if data.get("isMappingIdentifier"):
29
- if bool(self.__mapping_identifier_index is not None) and logger is not None:
30
- logger.info(
30
+ if bool(self.__mapping_identifier_index is not None):
31
+ KameleoonLogger.warning(
31
32
  "More than one mapping identifier is set. Undefined behavior may occur" +
32
33
  " on cross-device reconciliation."
33
34
  )
@@ -1,5 +1,5 @@
1
1
  """Kameleoon Configuration"""
2
- from logging import Logger
2
+
3
3
  from typing import Any, Dict, Optional
4
4
  from kameleoon.configuration.custom_data_info import CustomDataInfo
5
5
  from kameleoon.configuration.variation_by_exposition import VariationByExposition
@@ -7,6 +7,7 @@ from kameleoon.configuration.feature_flag import FeatureFlag
7
7
  from kameleoon.configuration.rule import Rule
8
8
  from kameleoon.configuration.settings import Settings
9
9
  from kameleoon.exceptions import FeatureNotFound, FeatureEnvironmentDisabled
10
+ from kameleoon.logging.kameleoon_logger import KameleoonLogger
10
11
 
11
12
 
12
13
  class DataFile:
@@ -15,11 +16,12 @@ class DataFile:
15
16
  @staticmethod
16
17
  def default(environment: Optional[str]) -> "DataFile":
17
18
  """Creates new instance of `DataFile` initialized with default values"""
18
- return DataFile(environment, Settings(), {}, CustomDataInfo(None))
19
+ data_file = DataFile(environment, Settings(), {}, CustomDataInfo(None))
20
+ return data_file
19
21
 
20
22
  @staticmethod
21
23
  def from_json(
22
- environment: Optional[str], configuration: Dict[str, Any], logger: Optional[Logger] = None
24
+ environment: Optional[str], configuration: Dict[str, Any]
23
25
  ) -> "DataFile":
24
26
  """Creates new instance of `DataFile` initialized from the specified configuration JSON"""
25
27
  settings = Settings(configuration.get("configuration"))
@@ -27,8 +29,9 @@ class DataFile:
27
29
  (feature_flag := FeatureFlag(jobj)).feature_key: feature_flag
28
30
  for jobj in configuration.get("featureFlags") or []
29
31
  }
30
- custom_data_info = CustomDataInfo(configuration.get("customData"), logger=logger)
31
- return DataFile(environment, settings, feature_flags, custom_data_info)
32
+ custom_data_info = CustomDataInfo(configuration.get("customData"))
33
+ data_file = DataFile(environment, settings, feature_flags, custom_data_info)
34
+ return data_file
32
35
 
33
36
  # pylint: disable=R0913
34
37
  def __init__(
@@ -38,6 +41,9 @@ class DataFile:
38
41
  feature_flags: Dict[str, FeatureFlag],
39
42
  custom_data_info: CustomDataInfo,
40
43
  ) -> None:
44
+ KameleoonLogger.debug(
45
+ 'CALL: DataFile(environment: %s, settings: %s, feature_flags: %s, custom_data_info: %s)',
46
+ environment, settings, feature_flags, custom_data_info)
41
47
  self.__environment = environment # pylint: disable=W0238
42
48
  self.__settings = settings
43
49
  self.__feature_flags: Dict[str, FeatureFlag] = feature_flags
@@ -52,6 +58,9 @@ class DataFile:
52
58
  self.__feature_flag_by_id: Dict[int, FeatureFlag] = {}
53
59
  self.__collect_indices()
54
60
  self.__custom_data_info = custom_data_info
61
+ KameleoonLogger.debug(
62
+ 'RETURN: DataFile.new(environment: %s, settings: %s, feature_flags: %s, custom_data_info: %s)',
63
+ environment, settings, feature_flags, custom_data_info)
55
64
 
56
65
  @property
57
66
  def settings(self) -> Settings:
@@ -109,3 +118,12 @@ class DataFile:
109
118
  for variation in rule.variation_by_exposition:
110
119
  if variation.variation_id is not None:
111
120
  self.__variation_by_id[variation.variation_id] = variation
121
+
122
+ def __str__(self):
123
+ return (
124
+ f"DataFile{{"
125
+ f"environment:'{self.__environment}',"
126
+ f"feature_flags:{len(self.__feature_flags)},"
127
+ f"settings:{self.__settings}"
128
+ f"}}"
129
+ )
@@ -4,6 +4,7 @@ from typing import Any, List, Dict, Optional
4
4
 
5
5
  from kameleoon.configuration.rule import Rule
6
6
  from kameleoon.configuration.variation import Variation
7
+ from kameleoon.helpers.string_utils import StringUtils
7
8
 
8
9
 
9
10
  class FeatureFlag:
@@ -29,3 +30,15 @@ class FeatureFlag:
29
30
  def get_variation(self, key: str) -> Optional[Variation]:
30
31
  """Retrun a variation for the given key"""
31
32
  return next((v for v in self.variations if v.key == key), None)
33
+
34
+ def __str__(self):
35
+ return (
36
+ f"FeatureFlag{{"
37
+ f"id:{self.id_},"
38
+ f"feature_key:'{self.feature_key}',"
39
+ f"environment_enabled:{self.environment_enabled},"
40
+ f"variations:{StringUtils.object_to_string(self.variations)},"
41
+ f"default_variation_key:'{self.default_variation_key}',"
42
+ f"rules:{len(self.rules)}"
43
+ f"}}"
44
+ )
@@ -54,3 +54,6 @@ class Rule:
54
54
  """Return `true` if rule is `targeted delivery` type"""
55
55
 
56
56
  return self.type == RuleType.TARGETED_DELIVERY
57
+
58
+ def __str__(self):
59
+ return f"Rule{{id:{self.id_}}}"
@@ -33,3 +33,10 @@ class Settings:
33
33
  def data_api_domain(self) -> Any:
34
34
  """Returns Data API domain to be switched to"""
35
35
  return self.__data_api_domain
36
+
37
+ def __str__(self):
38
+ return (
39
+ f"Settings{{real_time_update:{self.__real_time_update},"
40
+ f"is_consent_required:{self.__is_consent_required},"
41
+ f"data_api_domain:'{self.__data_api_domain}'}}"
42
+ )
@@ -4,6 +4,8 @@ from enum import Enum
4
4
  import json
5
5
  from typing import Any, List, Dict, Union
6
6
 
7
+ from kameleoon.helpers.string_utils import StringUtils
8
+
7
9
 
8
10
  class Variable:
9
11
  """
@@ -43,3 +45,8 @@ class Variable:
43
45
  def get_type(self) -> str:
44
46
  """Returns type value of variable"""
45
47
  return self.__type
48
+
49
+ def __str__(self):
50
+ return (f"Variable{{key:'{self.key},"
51
+ f"type:'{self.__type}',"
52
+ f"value:{StringUtils.object_to_string(self.__value)}}}")
@@ -4,6 +4,7 @@ from enum import Enum
4
4
  from typing import Any, List, Dict, Optional
5
5
 
6
6
  from kameleoon.configuration.variable import Variable
7
+ from kameleoon.helpers.string_utils import StringUtils
7
8
 
8
9
 
9
10
  class Variation:
@@ -29,3 +30,7 @@ class Variation:
29
30
  def get_variable_by_key(self, key: str) -> Optional[Variable]:
30
31
  """Retrun a variable for the given key"""
31
32
  return next((v for v in self.variables if v.key == key), None)
33
+
34
+ def __str__(self):
35
+ return (f"Variation{{key:'{self.key}',"
36
+ f"variables:{StringUtils.object_to_string(self.variables)}}}")
@@ -17,3 +17,10 @@ class VariationByExposition:
17
17
  self.variation_key: str = dict_json.get("variationKey", "")
18
18
  self.variation_id: Optional[int] = dict_json.get("variationId")
19
19
  self.exposition: float = dict_json.get("exposition", 0.0)
20
+
21
+ def __str__(self):
22
+ return (
23
+ f"VariationByExposition{{exposition:{self.exposition},"
24
+ f"variation_key:'{self.variation_key}',"
25
+ f"variation_id:{self.variation_id}}}"
26
+ )
@@ -1,29 +1,31 @@
1
1
  """ Imports all kameleoon data objects """
2
2
 
3
- from .custom_data import CustomData
4
3
  from .browser import Browser, BrowserType
5
4
  from .conversion import Conversion
6
- from .device import Device, DeviceType
7
- from .page_view import PageView
8
- from .user_agent import UserAgent
9
- from .data import Data, DataType
10
5
  from .cookie import Cookie
6
+ from .custom_data import CustomData
7
+ from .data import Data, DataType
8
+ from .device import Device, DeviceType
11
9
  from .geolocation import Geolocation
12
10
  from .operating_system import OperatingSystem, OperatingSystemType
11
+ from .page_view import PageView
12
+ from .user_agent import UserAgent
13
+ from .unique_identifier import UniqueIdentifier
13
14
 
14
15
  __all__ = [
15
- "CustomData",
16
16
  "Browser",
17
17
  "BrowserType",
18
18
  "Conversion",
19
- "Device",
20
- "DeviceType",
21
- "PageView",
22
- "UserAgent",
19
+ "Cookie",
20
+ "CustomData",
23
21
  "Data",
24
22
  "DataType",
25
- "Cookie",
23
+ "Device",
24
+ "DeviceType",
26
25
  "Geolocation",
27
- "OperatingSystemType",
28
26
  "OperatingSystem",
27
+ "OperatingSystemType",
28
+ "PageView",
29
+ "UserAgent",
30
+ "UniqueIdentifier",
29
31
  ]
@@ -51,10 +51,16 @@ class Browser(Data, DuplicationUnsafeSendableBase):
51
51
  def data_type(self) -> DataType:
52
52
  return DataType.BROWSER
53
53
 
54
- def _add_query_params(self, qb: QueryBuilder) -> None:
55
- qb.extend(
54
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
55
+ query_builder.extend(
56
56
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
57
57
  QueryParam(QueryParams.BROWSER_INDEX, str(self.browser_type.value)),
58
58
  )
59
59
  if self.version:
60
- qb.append(QueryParam(QueryParams.BROWSER_VERSION, str(self.version)))
60
+ query_builder.append(QueryParam(QueryParams.BROWSER_VERSION, str(self.version)))
61
+
62
+ def __str__(self):
63
+ return (
64
+ f"Browser{{browser_type:{self.__browser_type},"
65
+ f"version:{self.__version}}}"
66
+ )
@@ -51,12 +51,19 @@ class Conversion(Data, DuplicationSafeSendableBase):
51
51
  def data_type(self) -> DataType:
52
52
  return DataType.CONVERSION
53
53
 
54
- def _add_query_params(self, qb: QueryBuilder) -> None:
54
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
55
55
  # remove query_builder, it's done due due pylint issue with R0801 - duplicate_code,
56
56
  # need to update pylint and return str(QueryBuilder) straightaway
57
- qb.extend(
57
+ query_builder.extend(
58
58
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
59
59
  QueryParam(QueryParams.GOAL_ID, str(self.goal_id)),
60
60
  QueryParam(QueryParams.REVENUE, str(self.revenue)),
61
61
  QueryParam(QueryParams.NEGATIVE, "true" if self.negative else "false"),
62
62
  )
63
+
64
+ def __str__(self):
65
+ return (
66
+ f"Conversion{{goal_id:{self.__goal_id},"
67
+ f"revenue:{self.__revenue},"
68
+ f"negative:{self.__negative}}}"
69
+ )
@@ -30,3 +30,6 @@ class Cookie(Data):
30
30
  @property
31
31
  def data_type(self) -> DataType:
32
32
  return DataType.COOKIE
33
+
34
+ def __str__(self):
35
+ return f"Cookie{{cookies:{self.__cookies}}}"
@@ -30,7 +30,6 @@ class CustomData(Data, DuplicationUnsafeSendableBase):
30
30
  # pylint: disable=W0511
31
31
  self.__id = id
32
32
  self.__values = args
33
- self.is_mapping_identifier: bool = False
34
33
 
35
34
  @property
36
35
  def id(self) -> int: # pylint: disable=C0103
@@ -49,13 +48,17 @@ class CustomData(Data, DuplicationUnsafeSendableBase):
49
48
  def encode_query(self) -> str:
50
49
  return super().encode_query() if len(self.__values) > 0 else ""
51
50
 
52
- def _add_query_params(self, qb: QueryBuilder) -> None:
51
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
53
52
  str_values = json.dumps({v: 1 for v in self.__values}, separators=(",", ":"))
54
- qb.extend(
55
- QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
56
- QueryParam(QueryParams.INDEX, str(self.id)),
53
+ query_builder.extend(
54
+ QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE, False),
55
+ QueryParam(QueryParams.INDEX, str(self.id), False),
57
56
  QueryParam(QueryParams.VALUES_COUNT_MAP, str_values),
58
- QueryParam(QueryParams.OVERWRITE, "true"),
57
+ QueryParam(QueryParams.OVERWRITE, "true", False),
58
+ )
59
+
60
+ def __str__(self):
61
+ return (
62
+ f"CustomData{{id:{self.__id},"
63
+ f"values:{self.__values}}}"
59
64
  )
60
- if self.is_mapping_identifier:
61
- qb.append(QueryParam(QueryParams.MAPPING_IDENTIFIER, "true"))
@@ -19,6 +19,7 @@ class DataType(IntEnum):
19
19
  PAGE_VIEW_VISIT = 10
20
20
  VISITOR_VISITS = 11
21
21
  KCS_HEAT = 12
22
+ UNIQUE_IDENTIFIER = 13
22
23
 
23
24
 
24
25
  class BaseData:
@@ -31,7 +32,7 @@ class BaseData:
31
32
 
32
33
  def to_dict(self) -> Dict[str, Any]:
33
34
  """Convert class instance to dict"""
34
- return self.__dict__
35
+ return {k: str(v) for k, v in self.__dict__.items()}
35
36
 
36
37
 
37
38
  class Data(BaseData): # pylint: disable=W0223
@@ -40,8 +40,11 @@ class Device(Data, DuplicationUnsafeSendableBase):
40
40
  def data_type(self) -> DataType:
41
41
  return DataType.DEVICE
42
42
 
43
- def _add_query_params(self, qb: QueryBuilder) -> None:
44
- qb.extend(
43
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
44
+ query_builder.extend(
45
45
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
46
46
  QueryParam(QueryParams.DEVICE_TYPE, self.device_type.value),
47
47
  )
48
+
49
+ def __str__(self):
50
+ return f"Device{{device_type:{self.__device_type}}}"
@@ -82,19 +82,29 @@ class Geolocation(Data, DuplicationUnsafeSendableBase):
82
82
  def data_type(self) -> DataType:
83
83
  return DataType.GEOLOCATION
84
84
 
85
- def _add_query_params(self, qb: QueryBuilder) -> None:
86
- qb.extend(
85
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
86
+ query_builder.extend(
87
87
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
88
88
  )
89
89
  if self.country:
90
- qb.append(QueryParam(QueryParams.COUNTRY, self.country))
90
+ query_builder.append(QueryParam(QueryParams.COUNTRY, self.country))
91
91
  if self.region:
92
- qb.append(QueryParam(QueryParams.REGION, self.region))
92
+ query_builder.append(QueryParam(QueryParams.REGION, self.region))
93
93
  if self.city:
94
- qb.append(QueryParam(QueryParams.CITY, self.city))
94
+ query_builder.append(QueryParam(QueryParams.CITY, self.city))
95
95
  if self.postal_code:
96
- qb.append(QueryParam(QueryParams.POSTAL_CODE, self.postal_code))
96
+ query_builder.append(QueryParam(QueryParams.POSTAL_CODE, self.postal_code))
97
97
  if self.latitude is not None:
98
- qb.append(QueryParam(QueryParams.LATITUDE, str(self.latitude)))
98
+ query_builder.append(QueryParam(QueryParams.LATITUDE, str(self.latitude)))
99
99
  if self.longitude is not None:
100
- qb.append(QueryParam(QueryParams.LONGITUDE, str(self.longitude)))
100
+ query_builder.append(QueryParam(QueryParams.LONGITUDE, str(self.longitude)))
101
+
102
+ def __str__(self):
103
+ return (
104
+ f"Geolocation{{country:'{self.country}',"
105
+ f"region:'{self.region}',"
106
+ f"city:'{self.city}',"
107
+ f"postal_code:'{self.postal_code}',"
108
+ f"latitude:{self.latitude},"
109
+ f"longitude:{self.longitude}}}"
110
+ )
@@ -20,3 +20,6 @@ class KcsHeat(BaseData):
20
20
  @property
21
21
  def data_type(self) -> DataType:
22
22
  return DataType.KCS_HEAT
23
+
24
+ def __str__(self):
25
+ return f"KcsHeat{{values:{self.__values}}}"
@@ -0,0 +1,71 @@
1
+ """Assigned Variation"""
2
+ import time
3
+ from typing import Optional
4
+ from kameleoon.configuration.rule_type import RuleType
5
+ from kameleoon.data.data import BaseData, DataType
6
+ from kameleoon.network.sendable import DuplicationUnsafeSendableBase
7
+ from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
8
+
9
+
10
+ class AssignedVariation(BaseData, DuplicationUnsafeSendableBase):
11
+ """Assigned variation"""
12
+ EVENT_TYPE = "experiment"
13
+
14
+ def __init__(
15
+ self,
16
+ experiment_id: int,
17
+ variation_id: int,
18
+ rule_type: RuleType = RuleType.UNKNOWN,
19
+ assignment_time: Optional[float] = None,
20
+ ) -> None:
21
+ super().__init__()
22
+ self.__experiment_id = experiment_id
23
+ self.__variation_id = variation_id
24
+ self.__rule_type = rule_type
25
+ self.__assignment_time = assignment_time or time.time()
26
+
27
+ @property
28
+ def experiment_id(self) -> int:
29
+ """Returns the experiment ID."""
30
+ return self.__experiment_id
31
+
32
+ @property
33
+ def variation_id(self) -> int:
34
+ """Returns the variation ID."""
35
+ return self.__variation_id
36
+
37
+ @property
38
+ def rule_type(self) -> RuleType:
39
+ """Returns the rule type associated with the variation."""
40
+ return self.__rule_type
41
+
42
+ @property
43
+ def assignment_time(self) -> float:
44
+ """Returns the time when the assignment occurred."""
45
+ return self.__assignment_time
46
+
47
+ @property
48
+ def data_type(self) -> DataType:
49
+ """Returns the data type for the assigned variation."""
50
+ return DataType.ASSIGNED_VARIATION
51
+
52
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
53
+ # fmt: off
54
+ query_builder.extend(
55
+ QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
56
+ QueryParam(QueryParams.EXPERIMENT_ID, str(self.__experiment_id)),
57
+ QueryParam(QueryParams.VARIATION_ID, str(self.__variation_id)),
58
+ )
59
+ # fmt: on
60
+
61
+ def is_valid(self, respool_time: Optional[int]) -> bool:
62
+ """Checks if the assigned variation is valid based on the respool time."""
63
+ return (respool_time is None) or (self.assignment_time >= respool_time)
64
+
65
+ def __str__(self):
66
+ return (
67
+ f"AssignedVariation{{experiment_id:{self.__experiment_id},"
68
+ f"variation_id:{self.__variation_id},"
69
+ f"assignment_time:{self.__assignment_time},"
70
+ f"rule_type:{self.__rule_type}}}"
71
+ )