kameleoon-client-python 3.7.0__tar.gz → 3.9.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 (178) hide show
  1. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/PKG-INFO +1 -1
  2. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/data_file.py +41 -11
  3. kameleoon-client-python-3.9.0/kameleoon/configuration/experiment.py +46 -0
  4. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/feature_flag.py +3 -1
  5. kameleoon-client-python-3.9.0/kameleoon/configuration/me_group.py +24 -0
  6. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/rule.py +2 -27
  7. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/visitor.py +1 -1
  8. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/exceptions.py +1 -1
  9. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/functions.py +1 -39
  10. kameleoon-client-python-3.9.0/kameleoon/helpers/hasher.py +29 -0
  11. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/kameleoon_client.py +162 -100
  12. kameleoon-client-python-3.9.0/kameleoon/managers/evaluation/evaluated_experiment.py +50 -0
  13. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/cookie/cookie_manager.py +4 -2
  14. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/sdk_version.py +1 -1
  15. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +2 -2
  16. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon_client_python.egg-info/PKG-INFO +1 -1
  17. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon_client_python.egg-info/SOURCES.txt +5 -0
  18. kameleoon-client-python-3.9.0/tests/integration/proj/proj/__init__.py +0 -0
  19. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/MANIFEST.in +0 -0
  20. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/README.md +0 -0
  21. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/__init__.py +0 -0
  22. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/client_readiness/__init__.py +0 -0
  23. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/client_readiness/async_readiness.py +0 -0
  24. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/client_readiness/threading_readiness.py +0 -0
  25. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/__init__.py +0 -0
  26. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/custom_data_info.py +0 -0
  27. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/rule_type.py +0 -0
  28. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/settings.py +0 -0
  29. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/variable.py +0 -0
  30. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/variation.py +0 -0
  31. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/configuration/variation_by_exposition.py +0 -0
  32. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/__init__.py +0 -0
  33. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/browser.py +0 -0
  34. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/conversion.py +0 -0
  35. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/cookie.py +0 -0
  36. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/custom_data.py +0 -0
  37. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/data.py +0 -0
  38. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/device.py +0 -0
  39. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/geolocation.py +0 -0
  40. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/kcs_heat.py +0 -0
  41. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/__init__.py +0 -0
  42. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/assigned_variation.py +0 -0
  43. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/forced_experiment_variation.py +0 -0
  44. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/forced_feature_variation.py +0 -0
  45. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/forced_variation.py +0 -0
  46. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/page_view_visit.py +0 -0
  47. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/visitor_manager.py +0 -0
  48. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/manager/visitor_slot.py +0 -0
  49. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/mapping_identifier.py +0 -0
  50. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/operating_system.py +0 -0
  51. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/page_view.py +0 -0
  52. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/unique_identifier.py +0 -0
  53. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/user_agent.py +0 -0
  54. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/data/visitor_visits.py +0 -0
  55. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/defaults.py +0 -0
  56. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/__init__.py +0 -0
  57. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/domain.py +0 -0
  58. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/logger.py +0 -0
  59. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/multi_threading.py +0 -0
  60. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/nonce.py +0 -0
  61. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/repeat_timer.py +0 -0
  62. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/scheduler.py +0 -0
  63. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/string_utils.py +0 -0
  64. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/helpers/visitor_code.py +0 -0
  65. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/hybrid/__init__.py +0 -0
  66. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/hybrid/hybrid_manager.py +0 -0
  67. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/hybrid/hybrid_manager_impl.py +0 -0
  68. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/kameleoon_client_config.py +0 -0
  69. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/kameleoon_client_factory.py +0 -0
  70. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/logging/__init__.py +0 -0
  71. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/logging/kameleoon_logger.py +0 -0
  72. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/logging/log_level.py +0 -0
  73. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/logging/logger.py +0 -0
  74. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/__init__.py +0 -0
  75. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/asyncexec/__init__.py +0 -0
  76. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/asyncexec/async_executor.py +0 -0
  77. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/data/__init__.py +0 -0
  78. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/data/data_manager.py +0 -0
  79. {kameleoon-client-python-3.7.0/kameleoon/managers/remote_data → kameleoon-client-python-3.9.0/kameleoon/managers/evaluation}/__init__.py +0 -0
  80. {kameleoon-client-python-3.7.0/kameleoon/managers/tracking → kameleoon-client-python-3.9.0/kameleoon/managers/remote_data}/__init__.py +0 -0
  81. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/remote_data/remote_data_manager.py +0 -0
  82. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/remote_data/remote_visitor_data.py +0 -0
  83. {kameleoon-client-python-3.7.0/kameleoon/managers/warehouse → kameleoon-client-python-3.9.0/kameleoon/managers/tracking}/__init__.py +0 -0
  84. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/tracking/tracking_builder.py +0 -0
  85. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/tracking/tracking_manager.py +0 -0
  86. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/tracking/visitor_tracking_registry.py +0 -0
  87. {kameleoon-client-python-3.7.0/kameleoon/network → kameleoon-client-python-3.9.0/kameleoon/managers/warehouse}/__init__.py +0 -0
  88. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/managers/warehouse/warehouse_manager.py +0 -0
  89. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/middleware.py +0 -0
  90. {kameleoon-client-python-3.7.0/kameleoon/network/cookie → kameleoon-client-python-3.9.0/kameleoon/network}/__init__.py +0 -0
  91. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/access_token_source.py +0 -0
  92. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/access_token_source_factory.py +0 -0
  93. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/activity_event.py +0 -0
  94. {kameleoon-client-python-3.7.0/kameleoon/network/services → kameleoon-client-python-3.9.0/kameleoon/network/cookie}/__init__.py +0 -0
  95. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/net_provider.py +0 -0
  96. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/net_provider_impl.py +0 -0
  97. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/network_manager.py +0 -0
  98. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/network_manager_factory.py +0 -0
  99. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/network_manager_factory_impl.py +0 -0
  100. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/network_manager_impl.py +0 -0
  101. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/query_builder.py +0 -0
  102. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/query_encodable.py +0 -0
  103. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/sendable.py +0 -0
  104. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/service_initialize_context.py +0 -0
  105. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/service_initialize_context_impl.py +0 -0
  106. {kameleoon-client-python-3.7.0/kameleoon/real_time → kameleoon-client-python-3.9.0/kameleoon/network/services}/__init__.py +0 -0
  107. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/automation_service.py +0 -0
  108. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/automation_service_impl.py +0 -0
  109. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/configuration_service.py +0 -0
  110. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/configuration_service_impl.py +0 -0
  111. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/data_service.py +0 -0
  112. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/data_service_impl.py +0 -0
  113. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/service.py +0 -0
  114. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/services/service_impl.py +0 -0
  115. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/uri_helper.py +0 -0
  116. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/network/url_provider.py +0 -0
  117. {kameleoon-client-python-3.7.0/kameleoon/storage → kameleoon-client-python-3.9.0/kameleoon/real_time}/__init__.py +0 -0
  118. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/real_time/real_time_configuration_service.py +0 -0
  119. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/real_time/real_time_event.py +0 -0
  120. {kameleoon-client-python-3.7.0/kameleoon/targeting → kameleoon-client-python-3.9.0/kameleoon/storage}/__init__.py +0 -0
  121. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/storage/cache.py +0 -0
  122. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/storage/cache_factory.py +0 -0
  123. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/storage/cache_factory_impl.py +0 -0
  124. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/storage/cache_impl.py +0 -0
  125. {kameleoon-client-python-3.7.0/kameleoon/targeting/conditions → kameleoon-client-python-3.9.0/kameleoon/targeting}/__init__.py +0 -0
  126. {kameleoon-client-python-3.7.0/kameleoon/types → kameleoon-client-python-3.9.0/kameleoon/targeting/conditions}/__init__.py +0 -0
  127. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/browser_condition.py +0 -0
  128. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/constants.py +0 -0
  129. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/conversion_condition.py +0 -0
  130. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/cookie_condition.py +0 -0
  131. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/custom_datum.py +0 -0
  132. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/device_condition.py +0 -0
  133. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/exclusive_feature_flag_condition.py +0 -0
  134. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/geolocation_condition.py +0 -0
  135. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
  136. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/number_condition.py +0 -0
  137. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/operating_system_condition.py +0 -0
  138. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/page_title_condition.py +0 -0
  139. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/page_url_condition.py +0 -0
  140. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
  141. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
  142. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/sdk_language_condition.py +0 -0
  143. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/segment_condition.py +0 -0
  144. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/string_value_condition.py +0 -0
  145. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/targeting_condition.py +0 -0
  146. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +0 -0
  147. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/unknown_condition.py +0 -0
  148. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +0 -0
  149. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
  150. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
  151. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +0 -0
  152. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/models.py +0 -0
  153. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/targeting_manager.py +0 -0
  154. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/tree_builder.py +0 -0
  155. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/targeting/tree_condition_factory.py +0 -0
  156. {kameleoon-client-python-3.7.0/tests/integration/proj → kameleoon-client-python-3.9.0/kameleoon/types}/__init__.py +0 -0
  157. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/types/remote_visitor_data_filter.py +0 -0
  158. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/types/variable.py +0 -0
  159. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon/types/variation.py +0 -0
  160. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
  161. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon_client_python.egg-info/requires.txt +12 -12
  162. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
  163. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/setup.cfg +0 -0
  164. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/setup.py +0 -0
  165. {kameleoon-client-python-3.7.0/tests/integration/proj/kameleoon_app → kameleoon-client-python-3.9.0/tests/integration/proj}/__init__.py +0 -0
  166. {kameleoon-client-python-3.7.0/tests/integration/proj/kameleoon_app/migrations → kameleoon-client-python-3.9.0/tests/integration/proj/kameleoon_app}/__init__.py +0 -0
  167. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
  168. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
  169. {kameleoon-client-python-3.7.0/tests/integration/proj/proj → kameleoon-client-python-3.9.0/tests/integration/proj/kameleoon_app/migrations}/__init__.py +0 -0
  170. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
  171. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
  172. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
  173. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/manage.py +0 -0
  174. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/proj/asgi.py +0 -0
  175. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/proj/settings.py +0 -0
  176. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/proj/urls.py +0 -0
  177. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.0}/tests/integration/proj/proj/wsgi.py +0 -0
  178. {kameleoon-client-python-3.7.0 → kameleoon-client-python-3.9.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.7.0
3
+ Version: 3.9.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
@@ -1,12 +1,14 @@
1
1
  """Kameleoon Configuration"""
2
2
 
3
- from typing import Any, Dict, Optional, Set
3
+ from typing import Any, Dict, Iterable, List, Optional, Set
4
4
  from kameleoon.configuration import Variable
5
5
  from kameleoon.configuration.custom_data_info import CustomDataInfo
6
- from kameleoon.configuration.variation_by_exposition import VariationByExposition
6
+ from kameleoon.configuration.experiment import Experiment
7
7
  from kameleoon.configuration.feature_flag import FeatureFlag
8
+ from kameleoon.configuration.me_group import MEGroup
8
9
  from kameleoon.configuration.rule import Rule
9
10
  from kameleoon.configuration.settings import Settings
11
+ from kameleoon.configuration.variation_by_exposition import VariationByExposition
10
12
  from kameleoon.exceptions import FeatureNotFound, FeatureEnvironmentDisabled
11
13
  from kameleoon.logging.kameleoon_logger import KameleoonLogger
12
14
 
@@ -31,7 +33,8 @@ class DataFile:
31
33
  for jobj in configuration.get("featureFlags") or []
32
34
  }
33
35
  custom_data_info = CustomDataInfo(configuration.get("customData"))
34
- data_file = DataFile(environment, settings, feature_flags, custom_data_info)
36
+ holdout = Experiment.from_json(configuration["holdout"]) if "holdout" in configuration else None
37
+ data_file = DataFile(environment, settings, feature_flags, custom_data_info, holdout)
35
38
  return data_file
36
39
 
37
40
  # pylint: disable=R0913
@@ -41,13 +44,16 @@ class DataFile:
41
44
  settings: Settings,
42
45
  feature_flags: Dict[str, FeatureFlag],
43
46
  custom_data_info: CustomDataInfo,
47
+ holdout: Optional[Experiment] = None,
44
48
  ) -> None:
45
49
  KameleoonLogger.debug(
46
- 'CALL: DataFile(environment: %s, settings: %s, feature_flags: %s, custom_data_info: %s)',
47
- environment, settings, feature_flags, custom_data_info)
50
+ 'CALL: DataFile(environment: %s, settings: %s, feature_flags: %s, custom_data_info: %s, holdout: %s)',
51
+ environment, settings, feature_flags, custom_data_info, holdout
52
+ )
48
53
  self.__environment = environment # pylint: disable=W0238
49
54
  self.__settings = settings
50
55
  self.__feature_flags: Dict[str, FeatureFlag] = feature_flags
56
+ self.__me_groups = self.__make_me_groups(feature_flags.values())
51
57
  self.__has_any_targeted_delivery_rule = any(
52
58
  rule.is_targeted_delivery
53
59
  for ff in self.__feature_flags.values()
@@ -61,9 +67,11 @@ class DataFile:
61
67
  self.__experiment_ids_with_js_css_variable: Set[int] = set()
62
68
  self.__collect_indices()
63
69
  self.__custom_data_info = custom_data_info
70
+ self.__holdout = holdout
64
71
  KameleoonLogger.debug(
65
- 'RETURN: DataFile.new(environment: %s, settings: %s, feature_flags: %s, custom_data_info: %s)',
66
- environment, settings, feature_flags, custom_data_info)
72
+ 'RETURN: DataFile.new(environment: %s, settings: %s, feature_flags: %s, custom_data_info: %s, holdout: %s)',
73
+ environment, settings, feature_flags, custom_data_info
74
+ )
67
75
 
68
76
  @property
69
77
  def settings(self) -> Settings:
@@ -75,6 +83,11 @@ class DataFile:
75
83
  """Returns dictionary of all feature flags stored by feature keys"""
76
84
  return self.__feature_flags
77
85
 
86
+ @property
87
+ def me_groups(self) -> Dict[str, MEGroup]:
88
+ """Returns the mutually exclusive groups by their names"""
89
+ return self.__me_groups
90
+
78
91
  @property
79
92
  def feature_flag_by_id(self) -> Dict[int, FeatureFlag]:
80
93
  """Returns dictionary of all feature flags stored by id"""
@@ -114,9 +127,14 @@ class DataFile:
114
127
 
115
128
  @property
116
129
  def custom_data_info(self) -> CustomDataInfo:
117
- """Returns custom data info for mapping device`"""
130
+ """Returns custom data info for mapping device"""
118
131
  return self.__custom_data_info
119
132
 
133
+ @property
134
+ def holdout(self) -> Optional[Experiment]:
135
+ """Returns holdout"""
136
+ return self.__holdout
137
+
120
138
  def has_experiment_js_css_variable(self, experiment_id: int) -> bool:
121
139
  """Returns `True` if the experiment has a JS or CSS variable, otherwise returns `False`"""
122
140
  return experiment_id in self.__experiment_ids_with_js_css_variable
@@ -128,13 +146,25 @@ class DataFile:
128
146
  has_feature_flag_variable_js_css = self.__has_feature_flag_variable_js_css(feature_flag)
129
147
  for rule in feature_flag.rules:
130
148
  self.__rule_by_segment_id[rule.segment_id] = rule
131
- self.__rule_info_by_exp_id[rule.experiment_id] = DataFile.RuleInfo(feature_flag, rule)
149
+ self.__rule_info_by_exp_id[rule.experiment.id_] = DataFile.RuleInfo(feature_flag, rule)
132
150
  if has_feature_flag_variable_js_css:
133
- self.__experiment_ids_with_js_css_variable.add(rule.experiment_id)
134
- for variation in rule.variation_by_exposition:
151
+ self.__experiment_ids_with_js_css_variable.add(rule.experiment.id_)
152
+ for variation in rule.experiment.variations_by_exposition:
135
153
  if variation.variation_id is not None:
136
154
  self.__variation_by_id[variation.variation_id] = variation
137
155
 
156
+ @staticmethod
157
+ def __make_me_groups(feature_flags: Iterable[FeatureFlag]) -> Dict[str, MEGroup]:
158
+ me_group_lists: Dict[str, List[FeatureFlag]] = {}
159
+ for feature_flag in feature_flags:
160
+ if feature_flag.me_group_name:
161
+ me_group_list = me_group_lists.get(feature_flag.me_group_name)
162
+ if me_group_list:
163
+ me_group_list.append(feature_flag)
164
+ else:
165
+ me_group_lists[feature_flag.me_group_name] = [feature_flag]
166
+ return {me_group_name: MEGroup(me_group_list) for me_group_name, me_group_list in me_group_lists.items()}
167
+
138
168
  @staticmethod
139
169
  def __has_feature_flag_variable_js_css(feature_flag: FeatureFlag) -> bool:
140
170
  variations = feature_flag.variations
@@ -0,0 +1,46 @@
1
+ """Kameleoon Configuration"""
2
+
3
+ from typing import Any, List, Dict, Optional
4
+ from kameleoon.configuration.variation_by_exposition import VariationByExposition
5
+ from kameleoon.exceptions import FeatureVariationNotFound
6
+
7
+
8
+ class Experiment:
9
+ """Experiment"""
10
+
11
+ def __init__(self, id_: int, variations_by_exposition: List[VariationByExposition]) -> None:
12
+ self.id_ = id_
13
+ self.variations_by_exposition = variations_by_exposition
14
+ self.first_variation = variations_by_exposition[0] if len(variations_by_exposition) > 0 else None
15
+
16
+ @staticmethod
17
+ def from_json(dict_json: Dict[str, Any]) -> "Experiment":
18
+ """Creates a new instance of `Experiment` from a json object"""
19
+ id_ = dict_json.get("experimentId", 0)
20
+ variations_by_exposition: List[VariationByExposition] = VariationByExposition.from_array(
21
+ dict_json.get("variationByExposition", [])
22
+ )
23
+ return Experiment(id_, variations_by_exposition)
24
+
25
+ def get_variation(self, hash_double: float) -> Optional[VariationByExposition]:
26
+ """Calculates the variation key for the given hash of visitor"""
27
+
28
+ total = 0.0
29
+ for var_by_exp in self.variations_by_exposition:
30
+ total += var_by_exp.exposition
31
+ if total >= hash_double:
32
+ return var_by_exp
33
+ return None
34
+
35
+ def get_variation_by_key(self, variation_key: str) -> VariationByExposition:
36
+ """
37
+ Finds variation with a passed variation key.
38
+ Raises the `FeatureVariationNotFound` exception if such variation does not exist.
39
+ """
40
+ for var_by_exp in self.variations_by_exposition:
41
+ if var_by_exp.variation_key == variation_key:
42
+ return var_by_exp
43
+ raise FeatureVariationNotFound("'#{variation_key}'")
44
+
45
+ def __str__(self) -> str:
46
+ return f"Experiment{{id:{self.id_}}}"
@@ -17,10 +17,11 @@ class FeatureFlag:
17
17
  """Create a list of FeatureFlags from the json array"""
18
18
  return [FeatureFlag(item) for item in array]
19
19
 
20
- def __init__(self, dict_json: Dict[str, Any]):
20
+ def __init__(self, dict_json: Dict[str, Any]) -> None:
21
21
  self.id_: int = dict_json.get("id", 0)
22
22
  self.feature_key: str = dict_json.get("featureKey", "")
23
23
  self.default_variation_key: str = dict_json.get("defaultVariationKey", "")
24
+ self.me_group_name: Optional[str] = dict_json.get("mutuallyExclusiveGroup")
24
25
  self.variations: List[Variation] = Variation.from_array(
25
26
  dict_json.get("variations", [])
26
27
  )
@@ -39,6 +40,7 @@ class FeatureFlag:
39
40
  f"environment_enabled:{self.environment_enabled},"
40
41
  f"variations:{StringUtils.object_to_string(self.variations)},"
41
42
  f"default_variation_key:'{self.default_variation_key}',"
43
+ f"me_group_name:'{self.me_group_name}',"
42
44
  f"rules:{len(self.rules)}"
43
45
  f"}}"
44
46
  )
@@ -0,0 +1,24 @@
1
+ """Kameleoon Configuration"""
2
+
3
+ from typing import List
4
+ from kameleoon.configuration.feature_flag import FeatureFlag
5
+
6
+
7
+ class MEGroup:
8
+ """Represents a mutually exclusive group"""
9
+
10
+ def __init__(self, feature_flags: List[FeatureFlag]) -> None:
11
+ feature_flags.sort(key=lambda ff: ff.id_)
12
+ self.__feature_flags = feature_flags
13
+
14
+ @property
15
+ def feature_flags(self) -> List[FeatureFlag]:
16
+ """Returns the feature flags"""
17
+ return self.__feature_flags
18
+
19
+ def get_feature_flag_by_hash(self, hash_double: float) -> FeatureFlag:
20
+ """Finds a feature flag by the given hash"""
21
+ idx = int(hash_double * len(self.__feature_flags))
22
+ if idx >= len(self.__feature_flags):
23
+ idx = len(self.__feature_flags) - 1
24
+ return self.__feature_flags[idx]
@@ -1,9 +1,8 @@
1
1
  """Kameleoon Configuration"""
2
2
 
3
3
  from typing import Any, List, Dict, Optional
4
+ from kameleoon.configuration.experiment import Experiment
4
5
  from kameleoon.configuration.rule_type import RuleType, rule_type_from_literal
5
- from kameleoon.configuration.variation_by_exposition import VariationByExposition
6
- from kameleoon.exceptions import FeatureVariationNotFound
7
6
  from kameleoon.targeting.models import Segment
8
7
 
9
8
 
@@ -24,36 +23,12 @@ class Rule:
24
23
  type_literal: str = dict_json.get("type", "")
25
24
  self.type = rule_type_from_literal(type_literal)
26
25
  self.exposition: float = dict_json.get("exposition", 0.0)
27
- self.experiment_id: int = dict_json.get("experimentId", 0)
26
+ self.experiment = Experiment.from_json(dict_json)
28
27
  self.respool_time: Optional[int] = dict_json.get("respoolTime", None)
29
- self.variation_by_exposition: List[VariationByExposition] = VariationByExposition.from_array(
30
- dict_json.get("variationByExposition", [])
31
- )
32
- self.first_variation = self.variation_by_exposition[0] if len(self.variation_by_exposition) > 0 else None
33
28
  segment = dict_json.get("segment")
34
29
  self.targeting_segment: Optional[Segment] = Segment(segment) if segment else None
35
30
  self.segment_id: int = self.targeting_segment.id_ if self.targeting_segment else -1
36
31
 
37
- def get_variation(self, hash_double: float) -> Optional[VariationByExposition]:
38
- """Calculates the variation key for the given hash of visitor"""
39
-
40
- total = 0.0
41
- for var_by_exp in self.variation_by_exposition:
42
- total += var_by_exp.exposition
43
- if total >= hash_double:
44
- return var_by_exp
45
- return None
46
-
47
- def get_variation_by_key(self, variation_key: str) -> VariationByExposition:
48
- """
49
- Finds variation with a passed variation key.
50
- Raises the `FeatureVariationNotFound` exception if such variation does not exist.
51
- """
52
- for var_by_exp in self.variation_by_exposition:
53
- if var_by_exp.variation_key == variation_key:
54
- return var_by_exp
55
- raise FeatureVariationNotFound("'#{variation_key}'")
56
-
57
32
  @property
58
33
  def is_experimentation(self) -> bool:
59
34
  """Return `true` if rule is `experimentation` type"""
@@ -347,7 +347,7 @@ class Visitor: # pylint: disable=R0904
347
347
  fev = cast(ForcedExperimentVariation, context.data)
348
348
  if self._data.forced_variations is None:
349
349
  self._data.forced_variations = {}
350
- self._data.forced_variations[fev.rule.experiment_id] = fev
350
+ self._data.forced_variations[fev.rule.experiment.id_] = fev
351
351
 
352
352
  def _set_browser(self, context: DataAddingContext) -> None:
353
353
  if context.overwrite or self._data.browser is None:
@@ -70,7 +70,7 @@ class FeatureNotFound(NotFoundError):
70
70
  super().__init__(self.message)
71
71
 
72
72
 
73
- class FeatureExperimentNotFound(NotFoundError): # //~ Derived from FeatureError in other SDKs
73
+ class FeatureExperimentNotFound(NotFoundError):
74
74
  """Exception indicating that the requested experiment has not been found.
75
75
  Check that the experiment's ID matches the provided one."""
76
76
 
@@ -1,46 +1,8 @@
1
1
  """Helper functions"""
2
- import hashlib
3
2
  import json
4
- import math
5
3
  import sys
6
4
  from enum import Enum
7
- from typing import Dict, Any, Optional, Union, Type, TypeVar
8
-
9
-
10
- def obtain_hash_double(
11
- visitor_code: str, respool_times=None, container_id: str = ""
12
- ) -> float:
13
- """Calculate the hash value for a given visitor_code"""
14
- return _obtain_hash_double(visitor_code, respool_times, container_id)
15
-
16
-
17
- def obtain_hash_double_rule(
18
- visitor_code: str, container_id: int, respool_time: Optional[int] = None
19
- ) -> float:
20
- """Calculate the hash value for feature flag v2 for a given visitor_code"""
21
- return _obtain_hash_double(
22
- visitor_code=visitor_code,
23
- container_id=container_id,
24
- suffix=str(respool_time) if respool_time else "",
25
- )
26
-
27
-
28
- def _obtain_hash_double(
29
- visitor_code: str,
30
- respool_times=None,
31
- container_id: Union[str, int] = "",
32
- suffix: str = "",
33
- ) -> float:
34
- if respool_times is None:
35
- respool_times = {}
36
- identifier = visitor_code
37
- identifier += str(container_id)
38
- identifier += suffix
39
- if respool_times:
40
- identifier += "".join([str(v) for k, v in sorted(respool_times.items())])
41
- return int(hashlib.sha256(identifier.encode("UTF-8")).hexdigest(), 16) / math.pow(
42
- 2, 256
43
- )
5
+ from typing import Dict, Any, Optional, Type, TypeVar
44
6
 
45
7
 
46
8
  def load_params_from_json(json_path) -> Dict[Any, Any]:
@@ -0,0 +1,29 @@
1
+ """Helper hash functions"""
2
+
3
+ import hashlib
4
+ import math
5
+ from typing import Optional
6
+
7
+
8
+ class Hasher:
9
+ """Hasher"""
10
+
11
+ @staticmethod
12
+ def obtain(
13
+ visitor_code: str, container_id: int, respool_time: Optional[int] = None
14
+ ) -> float:
15
+ """Calculate the hash value for feature flag v2 for a given visitor_code"""
16
+ identifier = visitor_code
17
+ identifier += str(container_id)
18
+ if respool_time:
19
+ identifier += str(respool_time)
20
+ return Hasher._calculate(identifier)
21
+
22
+ @staticmethod
23
+ def obtain_hash_for_me_group(visitor_code: str, me_group_name: str) -> float:
24
+ """Calculate the hash value for a mutually exclusive group for a given visitor code"""
25
+ return Hasher._calculate(visitor_code + me_group_name)
26
+
27
+ @staticmethod
28
+ def _calculate(str_to_hash: str) -> float:
29
+ return int(hashlib.sha256(str_to_hash.encode("UTF-8")).hexdigest(), 16) / math.pow(2, 256)