kameleoon-client-python 3.14.0__tar.gz → 3.16.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 (185) hide show
  1. {kameleoon-client-python-3.14.0/kameleoon_client_python.egg-info → kameleoon-client-python-3.16.0}/PKG-INFO +1 -1
  2. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/custom_data_info.py +8 -1
  3. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/data_file.py +20 -14
  4. kameleoon-client-python-3.16.0/kameleoon/data/custom_data.py +90 -0
  5. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/data.py +1 -0
  6. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/assigned_variation.py +1 -1
  7. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/visitor.py +24 -2
  8. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/visitor_manager.py +8 -3
  9. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/mapping_identifier.py +2 -1
  10. kameleoon-client-python-3.16.0/kameleoon/data/targeted_segment.py +34 -0
  11. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/kameleoon_client.py +24 -1
  12. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/remote_data/remote_visitor_data.py +1 -1
  13. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/middleware.py +0 -1
  14. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/query_builder.py +1 -0
  15. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/sdk_version.py +1 -1
  16. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/exclusive_experiment_condition.py +3 -1
  17. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/segment_condition.py +2 -2
  18. kameleoon-client-python-3.16.0/kameleoon/targeting/models.py +28 -0
  19. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/targeting_manager.py +17 -15
  20. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0/kameleoon_client_python.egg-info}/PKG-INFO +1 -1
  21. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon_client_python.egg-info/SOURCES.txt +1 -0
  22. kameleoon-client-python-3.14.0/kameleoon/data/custom_data.py +0 -58
  23. kameleoon-client-python-3.14.0/kameleoon/targeting/models.py +0 -29
  24. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/MANIFEST.in +0 -0
  25. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/README.md +0 -0
  26. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/__init__.py +0 -0
  27. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/client_readiness/__init__.py +0 -0
  28. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/client_readiness/async_readiness.py +0 -0
  29. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/client_readiness/threading_readiness.py +0 -0
  30. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/__init__.py +0 -0
  31. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/experiment.py +0 -0
  32. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/feature_flag.py +0 -0
  33. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/me_group.py +0 -0
  34. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/rule.py +0 -0
  35. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/rule_type.py +0 -0
  36. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/settings.py +0 -0
  37. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/variable.py +0 -0
  38. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/variation.py +0 -0
  39. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/configuration/variation_by_exposition.py +0 -0
  40. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/__init__.py +0 -0
  41. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/browser.py +0 -0
  42. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/cbscores.py +0 -0
  43. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/conversion.py +0 -0
  44. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/cookie.py +0 -0
  45. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/device.py +0 -0
  46. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/geolocation.py +0 -0
  47. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/kcs_heat.py +0 -0
  48. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/__init__.py +0 -0
  49. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/forced_experiment_variation.py +0 -0
  50. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/forced_feature_variation.py +0 -0
  51. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/forced_variation.py +0 -0
  52. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/page_view_visit.py +0 -0
  53. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/manager/visitor_slot.py +0 -0
  54. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/operating_system.py +0 -0
  55. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/page_view.py +0 -0
  56. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/personalization.py +0 -0
  57. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/unique_identifier.py +0 -0
  58. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/user_agent.py +0 -0
  59. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/data/visitor_visits.py +0 -0
  60. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/defaults.py +0 -0
  61. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/exceptions.py +0 -0
  62. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/__init__.py +0 -0
  63. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/domain.py +0 -0
  64. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/functions.py +0 -0
  65. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/hasher.py +0 -0
  66. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/logger.py +0 -0
  67. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/multi_threading.py +0 -0
  68. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/nonce.py +0 -0
  69. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/repeat_timer.py +0 -0
  70. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/scheduler.py +0 -0
  71. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/string_utils.py +0 -0
  72. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/helpers/visitor_code.py +0 -0
  73. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/hybrid/__init__.py +0 -0
  74. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/hybrid/hybrid_manager.py +0 -0
  75. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/hybrid/hybrid_manager_impl.py +0 -0
  76. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/kameleoon_client_config.py +0 -0
  77. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/kameleoon_client_factory.py +0 -0
  78. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/logging/__init__.py +0 -0
  79. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/logging/kameleoon_logger.py +0 -0
  80. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/logging/log_level.py +0 -0
  81. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/logging/logger.py +0 -0
  82. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/__init__.py +0 -0
  83. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/asyncexec/__init__.py +0 -0
  84. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/asyncexec/async_executor.py +0 -0
  85. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/data/__init__.py +0 -0
  86. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/data/data_manager.py +0 -0
  87. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/evaluation/__init__.py +0 -0
  88. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/evaluation/evaluated_experiment.py +0 -0
  89. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/remote_data/__init__.py +0 -0
  90. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/remote_data/remote_data_manager.py +0 -0
  91. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/tracking/__init__.py +0 -0
  92. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/tracking/tracking_builder.py +0 -0
  93. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/tracking/tracking_manager.py +0 -0
  94. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/tracking/visitor_tracking_registry.py +0 -0
  95. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/warehouse/__init__.py +0 -0
  96. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/managers/warehouse/warehouse_manager.py +0 -0
  97. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/__init__.py +0 -0
  98. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/access_token_source.py +0 -0
  99. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/access_token_source_factory.py +0 -0
  100. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/activity_event.py +0 -0
  101. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/cookie/__init__.py +0 -0
  102. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/cookie/cookie_manager.py +0 -0
  103. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/net_provider.py +0 -0
  104. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/net_provider_impl.py +0 -0
  105. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/network_manager.py +0 -0
  106. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/network_manager_factory.py +0 -0
  107. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/network_manager_factory_impl.py +0 -0
  108. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/network_manager_impl.py +0 -0
  109. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/query_encodable.py +0 -0
  110. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/sendable.py +0 -0
  111. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/service_initialize_context.py +0 -0
  112. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/service_initialize_context_impl.py +0 -0
  113. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/__init__.py +0 -0
  114. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/automation_service.py +0 -0
  115. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/automation_service_impl.py +0 -0
  116. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/configuration_service.py +0 -0
  117. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/configuration_service_impl.py +0 -0
  118. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/data_service.py +0 -0
  119. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/data_service_impl.py +0 -0
  120. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/service.py +0 -0
  121. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/services/service_impl.py +0 -0
  122. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/uri_helper.py +0 -0
  123. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/network/url_provider.py +0 -0
  124. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/real_time/__init__.py +0 -0
  125. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/real_time/real_time_configuration_service.py +0 -0
  126. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/real_time/real_time_event.py +0 -0
  127. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/storage/__init__.py +0 -0
  128. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/storage/cache.py +0 -0
  129. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/storage/cache_factory.py +0 -0
  130. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/storage/cache_factory_impl.py +0 -0
  131. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/storage/cache_impl.py +0 -0
  132. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/__init__.py +0 -0
  133. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/__init__.py +0 -0
  134. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/browser_condition.py +0 -0
  135. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/constants.py +0 -0
  136. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/conversion_condition.py +0 -0
  137. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/cookie_condition.py +0 -0
  138. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/custom_datum.py +0 -0
  139. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/device_condition.py +0 -0
  140. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/geolocation_condition.py +0 -0
  141. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
  142. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/number_condition.py +0 -0
  143. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/operating_system_condition.py +0 -0
  144. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/page_title_condition.py +0 -0
  145. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/page_url_condition.py +0 -0
  146. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
  147. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
  148. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/sdk_language_condition.py +0 -0
  149. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/string_value_condition.py +0 -0
  150. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/target_experiment_condition.py +0 -0
  151. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +0 -0
  152. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/target_personalization_condition.py +0 -0
  153. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/targeting_condition.py +0 -0
  154. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +0 -0
  155. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/unknown_condition.py +0 -0
  156. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +0 -0
  157. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
  158. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
  159. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +0 -0
  160. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/tree_builder.py +0 -0
  161. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/targeting/tree_condition_factory.py +0 -0
  162. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/types/__init__.py +0 -0
  163. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/types/remote_visitor_data_filter.py +0 -0
  164. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/types/variable.py +0 -0
  165. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon/types/variation.py +0 -0
  166. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
  167. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon_client_python.egg-info/requires.txt +16 -16
  168. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
  169. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/setup.cfg +0 -0
  170. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/setup.py +0 -0
  171. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/__init__.py +0 -0
  172. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/__init__.py +0 -0
  173. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
  174. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
  175. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/migrations/__init__.py +0 -0
  176. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
  177. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
  178. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
  179. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/manage.py +0 -0
  180. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/proj/__init__.py +0 -0
  181. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/proj/asgi.py +0 -0
  182. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/proj/settings.py +0 -0
  183. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/proj/urls.py +0 -0
  184. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.0}/tests/integration/proj/proj/wsgi.py +0 -0
  185. {kameleoon-client-python-3.14.0 → kameleoon-client-python-3.16.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.14.0
3
+ Version: 3.16.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
@@ -18,6 +18,7 @@ class CustomDataInfo:
18
18
  self.__local_only = set()
19
19
  self.__visitor_scope = set()
20
20
  self.__custom_data_index_by_id = {}
21
+ self.__custom_data_index_by_name = {}
21
22
  if custom_data is not None:
22
23
  for data in custom_data:
23
24
  index = data.get("index")
@@ -29,6 +30,8 @@ class CustomDataInfo:
29
30
  self.__visitor_scope.add(index)
30
31
  if (id_ := data.get("id")) is not None:
31
32
  self.__custom_data_index_by_id[id_] = index
33
+ if (name := data.get("name")) is not None:
34
+ self.__custom_data_index_by_name[name] = index
32
35
  if data.get("isMappingIdentifier"):
33
36
  if bool(self.__mapping_identifier_index is not None):
34
37
  KameleoonLogger.warning(
@@ -55,5 +58,9 @@ class CustomDataInfo:
55
58
  return self.__mapping_identifier_index
56
59
 
57
60
  def get_custom_data_index_by_id(self, custom_data_id: int) -> Optional[int]:
58
- """Get corresponding custom data id by custom data index"""
61
+ """Get corresponding custom data index by custom data id"""
59
62
  return self.__custom_data_index_by_id.get(custom_data_id)
63
+
64
+ def get_custom_data_index_by_name(self, custom_data_name: str) -> Optional[int]:
65
+ """Get corresponding custom data index by custom data name"""
66
+ return self.__custom_data_index_by_name.get(custom_data_name)
@@ -20,7 +20,7 @@ class DataFile:
20
20
  @staticmethod
21
21
  def default(environment: Optional[str]) -> "DataFile":
22
22
  """Creates new instance of `DataFile` initialized with default values"""
23
- data_file = DataFile(environment, None, Settings(), {}, CustomDataInfo(None))
23
+ data_file = DataFile(environment, None, Settings(), {}, {}, CustomDataInfo(None))
24
24
  return data_file
25
25
 
26
26
  @staticmethod
@@ -33,13 +33,13 @@ class DataFile:
33
33
  custom_data_info = CustomDataInfo(configuration.get("customData"))
34
34
  feature_flags = DataFile.__parse_feature_flags(configuration, segments, custom_data_info)
35
35
  holdout = Experiment.from_json(configuration["holdout"]) if "holdout" in configuration else None
36
- data_file = DataFile(environment, last_modified, settings, feature_flags, custom_data_info, holdout)
36
+ data_file = DataFile(environment, last_modified, settings, segments, feature_flags, custom_data_info, holdout)
37
37
  return data_file
38
38
 
39
39
  @staticmethod
40
40
  def __parse_segments(configuration: Dict[str, Any]) -> Dict[int, Segment]:
41
41
  return {
42
- (seg := Segment(jobj)).id_: seg
42
+ (seg := Segment.from_json(jobj)).id_: seg
43
43
  for jobj in configuration.get("segments") or []
44
44
  }
45
45
 
@@ -58,18 +58,21 @@ class DataFile:
58
58
  environment: Optional[str],
59
59
  last_modified: Optional[str],
60
60
  settings: Settings,
61
+ segments: Dict[int, Segment],
61
62
  feature_flags: Dict[str, FeatureFlag],
62
63
  custom_data_info: CustomDataInfo,
63
64
  holdout: Optional[Experiment] = None,
64
65
  ) -> None:
65
66
  KameleoonLogger.debug(
66
- "CALL: DataFile(environment: %s, last_modified: %s, settings: %s, feature_flags: %s,"
67
+ "CALL: DataFile(environment: %s, last_modified: %s, settings: %s, segments, feature_flags,"
67
68
  " custom_data_info: %s, holdout: %s)",
68
- environment, last_modified, settings, feature_flags, custom_data_info, holdout
69
+ environment, last_modified, settings, custom_data_info, holdout
69
70
  )
70
71
  self.__environment = environment # pylint: disable=W0238
71
72
  self.__last_modified = last_modified
72
73
  self.__settings = settings
74
+ self.__segments = segments
75
+ self.__audience_tracking_segments = [seg for seg in segments.values() if seg.audience_tracking]
73
76
  self.__feature_flags: Dict[str, FeatureFlag] = feature_flags
74
77
  self.__me_groups = self.__make_me_groups(feature_flags.values())
75
78
  self.__has_any_targeted_delivery_rule = any(
@@ -79,7 +82,6 @@ class DataFile:
79
82
  for rule in ff.rules
80
83
  )
81
84
  self.__variation_by_id: Dict[int, VariationByExposition] = {}
82
- self.__rule_by_segment_id: Dict[int, Rule] = {}
83
85
  self.__rule_info_by_exp_id: Dict[int, DataFile.RuleInfo] = {}
84
86
  self.__feature_flag_by_id: Dict[int, FeatureFlag] = {}
85
87
  self.__experiment_ids_with_js_css_variable: Set[int] = set()
@@ -87,9 +89,9 @@ class DataFile:
87
89
  self.__custom_data_info = custom_data_info
88
90
  self.__holdout = holdout
89
91
  KameleoonLogger.debug(
90
- "RETURN: DataFile(environment: %s, last_modified: %s, settings: %s, feature_flags: %s,"
92
+ "RETURN: DataFile(environment: %s, last_modified: %s, settings: %s, segments, feature_flags,"
91
93
  " custom_data_info: %s, holdout: %s)",
92
- environment, last_modified, settings, feature_flags, custom_data_info, holdout
94
+ environment, last_modified, settings, custom_data_info, holdout
93
95
  )
94
96
 
95
97
  @property
@@ -102,6 +104,16 @@ class DataFile:
102
104
  """Returns settings"""
103
105
  return self.__settings
104
106
 
107
+ @property
108
+ def segments(self) -> Dict[int, Segment]:
109
+ """Returns segments"""
110
+ return self.__segments
111
+
112
+ @property
113
+ def audience_tracking_segments(self) -> List[Segment]:
114
+ """Returns audience tracking segments"""
115
+ return self.__audience_tracking_segments
116
+
105
117
  @property
106
118
  def feature_flags(self) -> Dict[str, FeatureFlag]:
107
119
  """Returns dictionary of all feature flags stored by feature keys"""
@@ -117,11 +129,6 @@ class DataFile:
117
129
  """Returns dictionary of all feature flags stored by id"""
118
130
  return self.__feature_flag_by_id
119
131
 
120
- @property
121
- def rule_by_segment_id(self) -> Dict[int, Rule]:
122
- """Returns dictionary of all rule stored by segment id"""
123
- return self.__rule_by_segment_id
124
-
125
132
  @property
126
133
  def rule_info_by_exp_id(self) -> Dict[int, "DataFile.RuleInfo"]:
127
134
  """Returns dictionary of all rule related info stored by experiment id"""
@@ -169,7 +176,6 @@ class DataFile:
169
176
  if feature_flag.rules is not None:
170
177
  has_feature_flag_variable_js_css = self.__has_feature_flag_variable_js_css(feature_flag)
171
178
  for rule in feature_flag.rules:
172
- self.__rule_by_segment_id[rule.segment_id] = rule
173
179
  self.__rule_info_by_exp_id[rule.experiment.id_] = DataFile.RuleInfo(feature_flag, rule)
174
180
  if has_feature_flag_variable_js_css:
175
181
  self.__experiment_ids_with_js_css_variable.add(rule.experiment.id_)
@@ -0,0 +1,90 @@
1
+ """Custom data"""
2
+
3
+ import json
4
+ from typing import Optional, Tuple, Union
5
+ from kameleoon.data.data import Data, DataType
6
+ from kameleoon.network.sendable import DuplicationUnsafeSendableBase
7
+ from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
8
+
9
+
10
+ class CustomData(Data, DuplicationUnsafeSendableBase):
11
+ """Custom data"""
12
+
13
+ EVENT_TYPE = "customData"
14
+
15
+ def __init__(self, index_or_name: Union[int, str], *args: str, overwrite=True) -> None:
16
+ """
17
+ :param index_or_name: Index or Name of the custom data. This field is mandatory.
18
+ :type index_or_name: Union[int, str]
19
+ :param args: Values of the custom data to be stored. This field is mandatory.
20
+ :type args: *str
21
+ :param overwrite: Flag to explicitly control how the values are stored and how they appear in reports.
22
+ This field is optional, `True` by default.
23
+ :type overwrite: bool
24
+ """
25
+ # pylint: disable=invalid-name,redefined-builtin
26
+ super().__init__()
27
+ # pylint: disable=W0511
28
+ if isinstance(index_or_name, int):
29
+ self.__index = index_or_name
30
+ self._name = None
31
+ else:
32
+ self.__index = -1
33
+ self._name = index_or_name
34
+ self.__values = args
35
+ self.__overwrite = overwrite
36
+
37
+ def _named_to_indexed(self, index: int) -> "CustomData":
38
+ """Makes an indexed Custom Data instance based on the current instance"""
39
+ custom_data = CustomData(index, *self.__values, overwrite=self.__overwrite)
40
+ custom_data._name = self._name
41
+ return custom_data
42
+
43
+ @property
44
+ def id(self) -> int: # pylint: disable=C0103
45
+ """
46
+ Deprecated. Please use `index` instead.
47
+
48
+ Returns index
49
+ """
50
+ return self.__index
51
+
52
+ @property
53
+ def index(self) -> int:
54
+ """Returns index"""
55
+ return self.__index
56
+
57
+ @property
58
+ def name(self) -> Optional[str]:
59
+ """Returns name"""
60
+ return self._name
61
+
62
+ @property
63
+ def values(self) -> Tuple[str, ...]:
64
+ """Returns values"""
65
+ return self.__values
66
+
67
+ @property
68
+ def overwrite(self) -> bool:
69
+ """Returns overwrite"""
70
+ return self.__overwrite
71
+
72
+ @property
73
+ def data_type(self) -> DataType:
74
+ return DataType.CUSTOM_DATA
75
+
76
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
77
+ str_values = json.dumps({v: 1 for v in self.__values}, separators=(",", ":"))
78
+ query_builder.extend(
79
+ QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE, False),
80
+ QueryParam(QueryParams.INDEX, str(self.id), False),
81
+ QueryParam(QueryParams.VALUES_COUNT_MAP, str_values),
82
+ QueryParam(QueryParams.OVERWRITE, "true" if self.__overwrite else "false", False),
83
+ )
84
+
85
+ def __str__(self):
86
+ return (
87
+ "CustomData{"
88
+ f"index:{self.__index},name:'{self._name}',values:{self.__values},overwrite:{self.__overwrite}"
89
+ "}"
90
+ )
@@ -24,6 +24,7 @@ class DataType(IntEnum):
24
24
  FORCED_FEATURE_VARIATION = 15
25
25
  CBS = 16
26
26
  PERSONALIZATION = 17
27
+ TARGETED_SEGMENT = 18
27
28
 
28
29
 
29
30
  class BaseData:
@@ -62,7 +62,7 @@ class AssignedVariation(BaseData, DuplicationUnsafeSendableBase):
62
62
  """Checks if the assigned variation is valid based on the respool time."""
63
63
  return (respool_time is None) or (self.assignment_time >= respool_time)
64
64
 
65
- def __str__(self):
65
+ def __str__(self) -> str:
66
66
  return (
67
67
  f"AssignedVariation{{experiment_id:{self.__experiment_id},"
68
68
  f"variation_id:{self.__variation_id},"
@@ -18,6 +18,7 @@ from kameleoon.data.mapping_identifier import MappingIdentifier
18
18
  from kameleoon.data.operating_system import OperatingSystem
19
19
  from kameleoon.data.page_view import PageView
20
20
  from kameleoon.data.personalization import Personalization
21
+ from kameleoon.data.targeted_segment import TargetedSegment
21
22
  from kameleoon.data.unique_identifier import UniqueIdentifier
22
23
  from kameleoon.data.user_agent import UserAgent
23
24
  from kameleoon.data.manager.assigned_variation import AssignedVariation
@@ -142,6 +143,13 @@ class Visitor: # pylint: disable=R0904
142
143
  KameleoonLogger.debug('CALL/RETURN: Visitor.personalizations -> (personalizations: %s)', personalizations)
143
144
  return personalizations
144
145
 
146
+ @property
147
+ def targeted_segments(self) -> Dict[int, TargetedSegment]:
148
+ """Returns the personalizations associated with this Visitor."""
149
+ targeted_segments = EMPTY_DICT if self._data.targeted_segments is None else self._data.targeted_segments.copy()
150
+ KameleoonLogger.debug('CALL/RETURN: Visitor.targeted_segments -> (targeted_segments: %s)', targeted_segments)
151
+ return targeted_segments
152
+
145
153
  def get_forced_feature_variation(self, feature_key: str) -> Optional[ForcedFeatureVariation]:
146
154
  """
147
155
  Returns an associated forced feature variation by its feature key if it is present.
@@ -219,6 +227,8 @@ class Visitor: # pylint: disable=R0904
219
227
  KameleoonLogger.debug('CALL: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
220
228
  with self._data.lock:
221
229
  for data in args:
230
+ if data is None:
231
+ continue
222
232
  data_type = type(data)
223
233
  data_adder = self.DATA_ADDERS.get(data_type)
224
234
  if data_adder:
@@ -283,6 +293,7 @@ class Visitor: # pylint: disable=R0904
283
293
  self.conversions: Optional[List[Conversion]] = None
284
294
  self.variations: Optional[Dict[int, AssignedVariation]] = None
285
295
  self.personalizations: Optional[Dict[int, Personalization]] = None
296
+ self.targeted_segments: Optional[Dict[int, TargetedSegment]] = None
286
297
  self.forced_variations: Optional[Dict[int, ForcedExperimentVariation]] = None
287
298
  self.simulated_variations: Optional[Dict[str, ForcedFeatureVariation]] = None
288
299
  self.kcs_heat: Optional[KcsHeat] = None
@@ -309,6 +320,8 @@ class Visitor: # pylint: disable=R0904
309
320
  yield from (visit.page_view for visit in list(self.page_view_visits.values()))
310
321
  if self.variations is not None:
311
322
  yield from list(self.variations.values())
323
+ if self.targeted_segments is not None:
324
+ yield from list(self.targeted_segments.values())
312
325
  if self.conversions is not None:
313
326
  yield from list(self.conversions)
314
327
 
@@ -331,6 +344,8 @@ class Visitor: # pylint: disable=R0904
331
344
  count += len(self.page_view_visits)
332
345
  if self.variations is not None:
333
346
  count += len(self.variations)
347
+ if self.targeted_segments is not None:
348
+ count += len(self.targeted_segments)
334
349
  if self.conversions is not None:
335
350
  count += len(self.conversions)
336
351
  return count
@@ -374,6 +389,12 @@ class Visitor: # pylint: disable=R0904
374
389
  if context.overwrite or personalization.id not in self._data.personalizations:
375
390
  self._data.personalizations[personalization.id] = personalization
376
391
 
392
+ def _add_targeted_segment(self, context: DataAddingContext) -> None:
393
+ targeted_segment = cast(TargetedSegment, context.data)
394
+ if self._data.targeted_segments is None:
395
+ self._data.targeted_segments = {}
396
+ self._data.targeted_segments[targeted_segment.id] = targeted_segment
397
+
377
398
  def _add_forced_feature_variation(self, context: DataAddingContext) -> None:
378
399
  ffv = cast(ForcedFeatureVariation, context.data)
379
400
  if self._data.simulated_variations is None:
@@ -405,8 +426,8 @@ class Visitor: # pylint: disable=R0904
405
426
  custom_data = cast(CustomData, context.data)
406
427
  if self._data.custom_data_dict is None:
407
428
  self._data.custom_data_dict = {}
408
- if context.overwrite or custom_data.id not in self._data.custom_data_dict:
409
- self._data.custom_data_dict[custom_data.id] = custom_data
429
+ if context.overwrite or custom_data.index not in self._data.custom_data_dict:
430
+ self._data.custom_data_dict[custom_data.index] = custom_data
410
431
 
411
432
  def _add_page_view(self, context: DataAddingContext) -> None:
412
433
  page_view = cast(PageView, context.data)
@@ -471,6 +492,7 @@ class Visitor: # pylint: disable=R0904
471
492
  VisitorVisits: _set_visitor_visits,
472
493
  AssignedVariation: _add_variation,
473
494
  Personalization: _add_personalization,
495
+ TargetedSegment: _add_targeted_segment,
474
496
  ForcedFeatureVariation: _add_forced_feature_variation,
475
497
  ForcedExperimentVariation: _add_forced_experiment_variation,
476
498
  UniqueIdentifier: _set_is_unique_identifier,
@@ -87,15 +87,20 @@ class VisitorManager:
87
87
 
88
88
  def __process_custom_data(
89
89
  self, visitor_code: str, visitor: Visitor, custom_data_info: CustomDataInfo, custom_data: CustomData
90
- ) -> CustomData:
90
+ ) -> Optional[CustomData]:
91
91
  """Processes custom data, potentially modifying or mapping it based on certain conditions."""
92
+ if custom_data.name is not None:
93
+ cd_index = custom_data_info.get_custom_data_index_by_name(custom_data.name)
94
+ if cd_index is None:
95
+ return None
96
+ custom_data = custom_data._named_to_indexed(cd_index)
92
97
  # We shouldn't send custom data with local only type
93
- if custom_data_info.is_local_only(custom_data.id):
98
+ if custom_data_info.is_local_only(custom_data.index):
94
99
  custom_data.mark_as_sent()
95
100
  # If mappingIdentifier is passed, we should link anonymous visitor with real unique userId.
96
101
  # After authorization, customer must be able to continue work with userId, but hash for variation
97
102
  # should be calculated based on anonymous visitor code, that's why set MappingIdentifier to visitor.
98
- if custom_data_info.is_mapping_identifier(custom_data.id) and custom_data.values and custom_data.values[0]:
103
+ if custom_data_info.is_mapping_identifier(custom_data.index) and custom_data.values and custom_data.values[0]:
99
104
  visitor.mapping_identifier = visitor_code
100
105
  user_id = custom_data.values[0]
101
106
  if visitor_code != user_id:
@@ -6,7 +6,8 @@ from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParam
6
6
  class MappingIdentifier(CustomData):
7
7
  """Mapping identifier"""
8
8
  def __init__(self, custom_data: CustomData) -> None:
9
- super().__init__(custom_data.id, *custom_data.values)
9
+ super().__init__(custom_data.index, *custom_data.values, overwrite=custom_data.overwrite)
10
+ self._name = custom_data.name
10
11
 
11
12
  @property
12
13
  def unsent(self) -> bool:
@@ -0,0 +1,34 @@
1
+ """Targeted Segment"""
2
+ from kameleoon.data.data import BaseData, DataType
3
+ from kameleoon.network.sendable import DuplicationUnsafeSendableBase
4
+ from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
5
+
6
+
7
+ class TargetedSegment(BaseData, DuplicationUnsafeSendableBase):
8
+ """Targeted Segment"""
9
+ EVENT_TYPE = "targetingSegment"
10
+
11
+ def __init__(self, id_: int) -> None:
12
+ super().__init__()
13
+ self.__id = id_
14
+
15
+ @property
16
+ def id(self) -> int: # pylint: disable=C0103
17
+ """Returns the segment ID."""
18
+ return self.__id
19
+
20
+ @property
21
+ def data_type(self) -> DataType:
22
+ """Returns the data type for the targeted segment."""
23
+ return DataType.TARGETED_SEGMENT
24
+
25
+ def _add_query_params(self, query_builder: QueryBuilder) -> None:
26
+ # fmt: off
27
+ query_builder.extend(
28
+ QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
29
+ QueryParam(QueryParams.SEGMENT_ID, str(self.__id)),
30
+ )
31
+ # fmt: on
32
+
33
+ def __str__(self) -> str:
34
+ return f"TargetedSegment{{id:{self.__id}}}"
@@ -17,6 +17,7 @@ from kameleoon.data.manager.assigned_variation import AssignedVariation
17
17
  from kameleoon.data.manager.forced_experiment_variation import ForcedExperimentVariation
18
18
  from kameleoon.data.manager.visitor import Visitor
19
19
  from kameleoon.data.manager.visitor_manager import VisitorManager
20
+ from kameleoon.data.targeted_segment import TargetedSegment
20
21
 
21
22
  from kameleoon.exceptions import (
22
23
  FeatureVariationNotFound,
@@ -1380,7 +1381,7 @@ class KameleoonClient:
1380
1381
  campaign_id,
1381
1382
  rule,
1382
1383
  )
1383
- targeting = self._targeting_manager.check_targeting(visitor_code, campaign_id, rule)
1384
+ targeting = self._targeting_manager.check_targeting(visitor_code, campaign_id, rule.targeting_segment)
1384
1385
  KameleoonLogger.debug(
1385
1386
  "RETURN: KameleoonClient.__check_targeting(visitor_code: %s, campaign_id: %s, rule: %s) -> "
1386
1387
  "(targeting: %s)",
@@ -1782,3 +1783,25 @@ class KameleoonClient:
1782
1783
  variation_key,
1783
1784
  force_targeting,
1784
1785
  )
1786
+
1787
+ def evaluate_audiences(self, visitor_code: str) -> None:
1788
+ """
1789
+ Evaluates the visitor against all available Audiences Explorer segments and tracks those that match.
1790
+ A detailed analysis of segment performance can then be performed directly in Audiences Explorer.
1791
+
1792
+ :param visitor_code: The unique visitor code identifying the visitor.
1793
+ :type visitor_code: str
1794
+
1795
+ :raises VisitorCodeInvalid: The provided **visitor code** is invalid.
1796
+ """
1797
+ KameleoonLogger.info("CALL: KameleoonClient.evaluate_audiences(visitor_code: %s)", visitor_code)
1798
+ validate_visitor_code(visitor_code)
1799
+ segments = [
1800
+ TargetedSegment(seg.id_)
1801
+ for seg in self._data_manager.data_file.audience_tracking_segments
1802
+ if self._targeting_manager.check_targeting(visitor_code, None, seg)
1803
+ ]
1804
+ if segments:
1805
+ self._visitor_manager.add_data(visitor_code, *segments)
1806
+ self._tracking_manager.add_visitor_code(visitor_code)
1807
+ KameleoonLogger.info("RETURN: KameleoonClient.evaluate_audiences(visitor_code: %s)", visitor_code)
@@ -103,7 +103,7 @@ class RemoteVisitorData:
103
103
  """Marks data as sent based on the provided `custom_data_info`."""
104
104
  if self.__custom_data_dict:
105
105
  for data in self.__custom_data_dict.values():
106
- if custom_data_info is None or not custom_data_info.is_visitor_scope(data.id):
106
+ if custom_data_info is None or not custom_data_info.is_visitor_scope(data.index):
107
107
  data.mark_as_sent()
108
108
  if self.__experiments:
109
109
  for experiment in self.__experiments.values():
@@ -32,7 +32,6 @@ class KameleoonWSGIMiddleware:
32
32
  environ["HTTP_COOKIE"] = f"{VISITOR_CODE_COOKIE}={visitor_code}"
33
33
 
34
34
  def _custom_start_response(status, headers, exc_info=None):
35
- # pylint: disable=W0212
36
35
  self._client._cookie_manager.update(visitor_code, self._client._is_consent_given(visitor_code), cookies)
37
36
  headers.append(("Set-Cookie", cookies.output(header="")))
38
37
  return start_response(status, headers, exc_info)
@@ -48,6 +48,7 @@ class QueryParams(str, Enum):
48
48
  REVENUE = "revenue"
49
49
  SDK_NAME = "sdkName"
50
50
  SDK_VERSION = "sdkVersion"
51
+ SEGMENT_ID = "id"
51
52
  SITE_CODE = "siteCode"
52
53
  STATIC_DATA = "staticData"
53
54
  TIME_SINCE_PREVIOUS_VISIT = "timeSincePreviousVisit"
@@ -4,7 +4,7 @@ from typing import Optional, Tuple
4
4
 
5
5
  from kameleoon.logging.kameleoon_logger import KameleoonLogger
6
6
 
7
- version_info = (3, 14, 0)
7
+ version_info = (3, 16, 0)
8
8
  __version__ = ".".join(str(v) for v in version_info) # uses in scripts
9
9
 
10
10
 
@@ -35,7 +35,9 @@ class ExclusiveExperimentCondition(TargetingCondition):
35
35
  super().__init__(json_condition)
36
36
  self.__campaign_type = json_condition.get("campaignType")
37
37
 
38
- def check(self, data: TargetingData) -> bool:
38
+ def check(self, data: Any) -> bool:
39
+ if not isinstance(data, self.TargetingData):
40
+ return False
39
41
  if self.__campaign_type == self.CampaignType.EXPERIMENT:
40
42
  return self.__check_experiment(data)
41
43
  if self.__campaign_type == self.CampaignType.PERSONALIZATION:
@@ -42,5 +42,5 @@ class SegmentCondition(TargetingCondition):
42
42
  return isinstance(data, SegmentCondition.SegmentInfo) and self.__check(data)
43
43
 
44
44
  def __check(self, segment_info: SegmentInfo) -> bool:
45
- rule = segment_info.data_file().rule_by_segment_id.get(self.__segment_id)
46
- return rule is not None and rule.targeting_segment.check_tree(segment_info.condition_data())
45
+ segment = segment_info.data_file().segments.get(self.__segment_id)
46
+ return segment is not None and segment.check_tree(segment_info.condition_data())
@@ -0,0 +1,28 @@
1
+ """Targeting Segment"""
2
+
3
+ from typing import Any, Dict, Optional
4
+ from kameleoon.targeting.tree_builder import create_tree, Tree
5
+
6
+
7
+ class Segment:
8
+ """Segment with targeting data"""
9
+
10
+ def __init__(self, id_: int, tree: Optional[Tree], audience_tracking: bool) -> None:
11
+ self.id_ = id_
12
+ self.tree = tree
13
+ self.audience_tracking = audience_tracking
14
+
15
+ @staticmethod
16
+ def from_json(obj: Dict[str, Any]) -> "Segment":
17
+ """Creates a Segment instance from JSON object"""
18
+ id_ = obj.get("id", -1)
19
+ tree = create_tree(obj.get("conditionsData"))
20
+ audience_tracking = obj.get("audienceTracking", False)
21
+ return Segment(id_, tree, audience_tracking)
22
+
23
+ def check_tree(self, get_targeting_data) -> Optional[bool]:
24
+ """Checks the targeting throught targeting tree"""
25
+ return self.tree.check(get_targeting_data) if self.tree else True
26
+
27
+ def __str__(self) -> str:
28
+ return f"Segment{{id:{self.id_},audience_tracking:{self.audience_tracking}}}"
@@ -1,7 +1,6 @@
1
1
  """Targeting Segment"""
2
2
 
3
3
  from typing import Optional
4
- from kameleoon.configuration.rule import Rule
5
4
  from kameleoon.data.manager.visitor import Visitor
6
5
  from kameleoon.data.manager.visitor_manager import VisitorManager
7
6
  from kameleoon.helpers.functions import enum_from_literal
@@ -16,6 +15,7 @@ from kameleoon.targeting.conditions.target_experiment_condition import TargetExp
16
15
  from kameleoon.targeting.conditions.target_personalization_condition import TargetPersonalizationCondition
17
16
  from kameleoon.targeting.conditions.targeting_condition import TargetingConditionType
18
17
  from kameleoon.targeting.conditions.visit_number_today_condition import VisitNumberTodayCondition
18
+ from kameleoon.targeting.models import Segment
19
19
 
20
20
 
21
21
  class TargetingManager:
@@ -26,22 +26,23 @@ class TargetingManager:
26
26
  self.__visitor_manager = visitor_manager
27
27
 
28
28
  # pylint: disable=W0238
29
- def check_targeting(self, visitor_code: str, campaign_id: int, rule: Rule):
29
+ def check_targeting(self, visitor_code: str, campaign_id: Optional[int], segment: Optional[Segment]):
30
30
  """Check if visitor is targeted for rule"""
31
31
  KameleoonLogger.debug(
32
- "CALL: TargetingManager.check_targeting(visitor_code: %s, campaign_id: %s, rule: %s)",
33
- visitor_code, campaign_id, rule
32
+ "CALL: TargetingManager.check_targeting(visitor_code: %s, campaign_id: %s, segment: %s)",
33
+ visitor_code, campaign_id, segment
34
34
  )
35
- segment = rule.targeting_segment
36
35
  if segment is None:
37
36
  targeting: Optional[bool] = True
38
37
  else:
39
38
  visitor = self.__visitor_manager.get_visitor(visitor_code)
40
- targeting = segment.check_tree(lambda type: self.__get_condition_data(type, visitor, visitor_code,
41
- campaign_id))
42
- KameleoonLogger.debug("RETURN: TargetingManager.check_targeting(visitor_code: %s, campaign_id: %s, "
43
- "rule: %s) -> (targeting: %s)",
44
- visitor_code, campaign_id, rule, targeting)
39
+ targeting = segment.check_tree(
40
+ lambda type: self.__get_condition_data(type, visitor, visitor_code, campaign_id)
41
+ )
42
+ KameleoonLogger.debug(
43
+ "RETURN: TargetingManager.check_targeting(visitor_code: %s, campaign_id: %s, "
44
+ "segment: %s) -> (targeting: %s)", visitor_code, campaign_id, segment, targeting
45
+ )
45
46
  return targeting
46
47
 
47
48
  # pylint: disable=R0911
@@ -50,9 +51,9 @@ class TargetingManager:
50
51
  condition_type_literal: str,
51
52
  visitor: Optional[Visitor],
52
53
  visitor_code: str,
53
- campaign_id: int,
54
+ campaign_id: Optional[int],
54
55
  ):
55
- # pylint: disable=E1101,W0212
56
+ # pylint: disable=E1101
56
57
  KameleoonLogger.debug(
57
58
  "CALL: TargetingManager.__get_condition_data(condition_type_literal: %s, visitor, visitor_code: %s, "
58
59
  "campaign_id: %s)", condition_type_literal, visitor_code, campaign_id
@@ -72,9 +73,10 @@ class TargetingManager:
72
73
  lambda type: self.__get_condition_data(type, visitor, visitor_code, campaign_id),
73
74
  )
74
75
  elif condition_type == TargetingConditionType.EXCLUSIVE_EXPERIMENT:
75
- condition_data = ExclusiveExperimentCondition.TargetingData(
76
- campaign_id, visitor.variations if visitor else {}, visitor.personalizations if visitor else {}
77
- )
76
+ if campaign_id is not None:
77
+ condition_data = ExclusiveExperimentCondition.TargetingData(
78
+ campaign_id, visitor.variations if visitor else {}, visitor.personalizations if visitor else {}
79
+ )
78
80
  elif condition_type == TargetingConditionType.VISITOR_CODE:
79
81
  condition_data = visitor_code
80
82
  elif condition_type == TargetingConditionType.SDK_LANGUAGE:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kameleoon-client-python
3
- Version: 3.14.0
3
+ Version: 3.16.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
@@ -39,6 +39,7 @@ kameleoon/data/mapping_identifier.py
39
39
  kameleoon/data/operating_system.py
40
40
  kameleoon/data/page_view.py
41
41
  kameleoon/data/personalization.py
42
+ kameleoon/data/targeted_segment.py
42
43
  kameleoon/data/unique_identifier.py
43
44
  kameleoon/data/user_agent.py
44
45
  kameleoon/data/visitor_visits.py