kameleoon-client-python 3.4.0__tar.gz → 3.6.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 (170) hide show
  1. {kameleoon-client-python-3.4.0/kameleoon_client_python.egg-info → kameleoon-client-python-3.6.0}/PKG-INFO +1 -1
  2. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/data_file.py +20 -1
  3. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/variable.py +4 -0
  4. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/manager/page_view_visit.py +9 -2
  5. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/manager/visitor.py +6 -1
  6. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/string_utils.py +6 -1
  7. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/hybrid/hybrid_manager_impl.py +11 -4
  8. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/kameleoon_client.py +197 -43
  9. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/remote_data/remote_data_manager.py +13 -13
  10. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/remote_data/remote_visitor_data.py +8 -0
  11. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/url_provider.py +1 -1
  12. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/sdk_version.py +1 -1
  13. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/page_title_condition.py +3 -5
  14. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/page_url_condition.py +3 -7
  15. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/types/remote_visitor_data_filter.py +8 -1
  16. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/types/variation.py +6 -1
  17. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0/kameleoon_client_python.egg-info}/PKG-INFO +1 -1
  18. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/MANIFEST.in +0 -0
  19. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/README.md +0 -0
  20. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/__init__.py +0 -0
  21. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/client_readiness/__init__.py +0 -0
  22. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/client_readiness/async_readiness.py +0 -0
  23. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/client_readiness/threading_readiness.py +0 -0
  24. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/__init__.py +0 -0
  25. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/custom_data_info.py +0 -0
  26. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/feature_flag.py +0 -0
  27. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/rule.py +0 -0
  28. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/rule_type.py +0 -0
  29. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/settings.py +0 -0
  30. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/variation.py +0 -0
  31. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/configuration/variation_by_exposition.py +0 -0
  32. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/__init__.py +0 -0
  33. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/browser.py +0 -0
  34. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/conversion.py +0 -0
  35. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/cookie.py +0 -0
  36. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/custom_data.py +0 -0
  37. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/data.py +0 -0
  38. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/device.py +0 -0
  39. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/geolocation.py +0 -0
  40. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/kcs_heat.py +0 -0
  41. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/manager/__init__.py +0 -0
  42. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/manager/assigned_variation.py +0 -0
  43. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/manager/visitor_manager.py +0 -0
  44. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/manager/visitor_slot.py +0 -0
  45. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/mapping_identifier.py +0 -0
  46. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/operating_system.py +0 -0
  47. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/page_view.py +0 -0
  48. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/unique_identifier.py +0 -0
  49. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/user_agent.py +0 -0
  50. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/data/visitor_visits.py +0 -0
  51. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/defaults.py +0 -0
  52. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/exceptions.py +0 -0
  53. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/__init__.py +0 -0
  54. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/domain.py +0 -0
  55. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/functions.py +0 -0
  56. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/logger.py +0 -0
  57. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/multi_threading.py +0 -0
  58. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/nonce.py +0 -0
  59. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/repeat_timer.py +0 -0
  60. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/scheduler.py +0 -0
  61. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/helpers/visitor_code.py +0 -0
  62. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/hybrid/__init__.py +0 -0
  63. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/hybrid/hybrid_manager.py +0 -0
  64. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/kameleoon_client_config.py +0 -0
  65. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/kameleoon_client_factory.py +0 -0
  66. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/logging/__init__.py +0 -0
  67. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/logging/kameleoon_logger.py +0 -0
  68. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/logging/log_level.py +0 -0
  69. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/logging/logger.py +0 -0
  70. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/__init__.py +0 -0
  71. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/asyncexec/__init__.py +0 -0
  72. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/asyncexec/async_executor.py +0 -0
  73. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/data/__init__.py +0 -0
  74. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/data/data_manager.py +0 -0
  75. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/remote_data/__init__.py +0 -0
  76. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/tracking/__init__.py +0 -0
  77. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/tracking/tracking_builder.py +0 -0
  78. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/tracking/tracking_manager.py +0 -0
  79. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/tracking/visitor_tracking_registry.py +0 -0
  80. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/warehouse/__init__.py +0 -0
  81. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/managers/warehouse/warehouse_manager.py +0 -0
  82. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/middleware.py +0 -0
  83. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/__init__.py +0 -0
  84. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/access_token_source.py +0 -0
  85. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/access_token_source_factory.py +0 -0
  86. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/activity_event.py +0 -0
  87. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/cookie/__init__.py +0 -0
  88. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/cookie/cookie_manager.py +0 -0
  89. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/net_provider.py +0 -0
  90. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/net_provider_impl.py +0 -0
  91. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/network_manager.py +0 -0
  92. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/network_manager_factory.py +0 -0
  93. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/network_manager_factory_impl.py +0 -0
  94. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/network_manager_impl.py +0 -0
  95. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/query_builder.py +0 -0
  96. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/query_encodable.py +0 -0
  97. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/sendable.py +0 -0
  98. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/service_initialize_context.py +0 -0
  99. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/service_initialize_context_impl.py +0 -0
  100. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/__init__.py +0 -0
  101. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/automation_service.py +0 -0
  102. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/automation_service_impl.py +0 -0
  103. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/configuration_service.py +0 -0
  104. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/configuration_service_impl.py +0 -0
  105. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/data_service.py +0 -0
  106. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/data_service_impl.py +0 -0
  107. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/service.py +0 -0
  108. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/services/service_impl.py +0 -0
  109. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/network/uri_helper.py +0 -0
  110. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/real_time/__init__.py +0 -0
  111. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/real_time/real_time_configuration_service.py +0 -0
  112. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/real_time/real_time_event.py +0 -0
  113. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/storage/__init__.py +0 -0
  114. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/storage/cache.py +0 -0
  115. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/storage/cache_factory.py +0 -0
  116. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/storage/cache_factory_impl.py +0 -0
  117. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/storage/cache_impl.py +0 -0
  118. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/__init__.py +0 -0
  119. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/__init__.py +0 -0
  120. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/browser_condition.py +0 -0
  121. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/constants.py +0 -0
  122. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/conversion_condition.py +0 -0
  123. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/cookie_condition.py +0 -0
  124. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/custom_datum.py +0 -0
  125. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/device_condition.py +0 -0
  126. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/exclusive_feature_flag_condition.py +0 -0
  127. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/geolocation_condition.py +0 -0
  128. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
  129. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/number_condition.py +0 -0
  130. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/operating_system_condition.py +0 -0
  131. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
  132. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
  133. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/sdk_language_condition.py +0 -0
  134. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/segment_condition.py +0 -0
  135. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/string_value_condition.py +0 -0
  136. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +0 -0
  137. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/targeting_condition.py +0 -0
  138. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +0 -0
  139. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/unknown_condition.py +0 -0
  140. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +0 -0
  141. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
  142. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
  143. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +0 -0
  144. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/models.py +0 -0
  145. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/targeting_manager.py +0 -0
  146. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/tree_builder.py +0 -0
  147. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/targeting/tree_condition_factory.py +0 -0
  148. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/types/__init__.py +0 -0
  149. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon/types/variable.py +0 -0
  150. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon_client_python.egg-info/SOURCES.txt +0 -0
  151. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
  152. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon_client_python.egg-info/requires.txt +14 -14
  153. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
  154. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/setup.cfg +0 -0
  155. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/setup.py +0 -0
  156. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/__init__.py +0 -0
  157. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/__init__.py +0 -0
  158. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
  159. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
  160. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/migrations/__init__.py +0 -0
  161. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
  162. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
  163. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
  164. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/manage.py +0 -0
  165. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/proj/__init__.py +0 -0
  166. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/proj/asgi.py +0 -0
  167. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/proj/settings.py +0 -0
  168. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/proj/urls.py +0 -0
  169. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.0}/tests/integration/proj/proj/wsgi.py +0 -0
  170. {kameleoon-client-python-3.4.0 → kameleoon-client-python-3.6.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.4.0
3
+ Version: 3.6.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,6 +1,7 @@
1
1
  """Kameleoon Configuration"""
2
2
 
3
- from typing import Any, Dict, Optional
3
+ from typing import Any, Dict, Optional, Set
4
+ from kameleoon.configuration import Variable
4
5
  from kameleoon.configuration.custom_data_info import CustomDataInfo
5
6
  from kameleoon.configuration.variation_by_exposition import VariationByExposition
6
7
  from kameleoon.configuration.feature_flag import FeatureFlag
@@ -56,6 +57,7 @@ class DataFile:
56
57
  self.__variation_by_id: Dict[int, VariationByExposition] = {}
57
58
  self.__rule_by_segment_id: Dict[int, Rule] = {}
58
59
  self.__feature_flag_by_id: Dict[int, FeatureFlag] = {}
60
+ self.__experiment_ids_with_js_css_variable: Set[int] = set()
59
61
  self.__collect_indices()
60
62
  self.__custom_data_info = custom_data_info
61
63
  KameleoonLogger.debug(
@@ -109,16 +111,33 @@ class DataFile:
109
111
  """Returns custom data info for mapping device`"""
110
112
  return self.__custom_data_info
111
113
 
114
+ def has_experiment_js_css_variable(self, experiment_id: int) -> bool:
115
+ """Returns `True` if the experiment has a JS or CSS variable, otherwise returns `False`"""
116
+ return experiment_id in self.__experiment_ids_with_js_css_variable
117
+
112
118
  def __collect_indices(self) -> None:
113
119
  for _, feature_flag in self.__feature_flags.items():
114
120
  self.__feature_flag_by_id[feature_flag.id_] = feature_flag
115
121
  if feature_flag.rules is not None:
122
+ has_feature_flag_variable_js_css = self.__has_feature_flag_variable_js_css(feature_flag)
116
123
  for rule in feature_flag.rules:
117
124
  self.__rule_by_segment_id[rule.segment_id] = rule
125
+ if has_feature_flag_variable_js_css:
126
+ self.__experiment_ids_with_js_css_variable.add(rule.experiment_id)
118
127
  for variation in rule.variation_by_exposition:
119
128
  if variation.variation_id is not None:
120
129
  self.__variation_by_id[variation.variation_id] = variation
121
130
 
131
+ @staticmethod
132
+ def __has_feature_flag_variable_js_css(feature_flag: FeatureFlag) -> bool:
133
+ variations = feature_flag.variations
134
+ first_variation = next(iter(variations), None)
135
+ if first_variation:
136
+ for variable in first_variation.variables:
137
+ if variable.get_type() in {Variable.Type.CSS.value, Variable.Type.JS.value}:
138
+ return True
139
+ return False
140
+
122
141
  def __str__(self):
123
142
  return (
124
143
  f"DataFile{{"
@@ -19,6 +19,8 @@ class Variable:
19
19
  JSON = "JSON"
20
20
  NUMBER = "NUMBER"
21
21
  STRING = "STRING"
22
+ CSS = "CSS"
23
+ JS = "JS"
22
24
 
23
25
  @staticmethod
24
26
  def from_array(array: List[Dict[str, Any]]) -> List["Variable"]:
@@ -36,6 +38,8 @@ class Variable:
36
38
  Variable.Type.BOOLEAN.value,
37
39
  Variable.Type.NUMBER.value,
38
40
  Variable.Type.STRING.value,
41
+ Variable.Type.CSS.value,
42
+ Variable.Type.JS.value,
39
43
  ):
40
44
  return self.__value
41
45
  if self.__type == Variable.Type.JSON.value and isinstance(self.__value, str):
@@ -1,4 +1,5 @@
1
1
  """Page view visit"""
2
+
2
3
  import time
3
4
  from typing import Optional
4
5
  from kameleoon.data import DataType
@@ -8,6 +9,7 @@ from kameleoon.data.page_view import PageView
8
9
 
9
10
  class PageViewVisit(BaseData):
10
11
  """Page view visit"""
12
+
11
13
  def __init__(self, page_view: PageView, count=1, last_timestamp: Optional[int] = None) -> None:
12
14
  super().__init__()
13
15
  self.page_view = page_view
@@ -18,6 +20,7 @@ class PageViewVisit(BaseData):
18
20
  """Overwrites the current PageView with a new PageView and increments the visit count."""
19
21
  self.page_view = new_page_view
20
22
  self.count += 1
23
+ self.last_timestamp = int(time.time() * 1000)
21
24
 
22
25
  def merge(self, page_view_visit) -> None:
23
26
  """Merges the visit data from another PageViewVisit instance into this one."""
@@ -33,8 +36,12 @@ class PageViewVisit(BaseData):
33
36
  return DataType.PAGE_VIEW_VISIT
34
37
 
35
38
  def __eq__(self, other: object) -> bool:
36
- return isinstance(other, PageViewVisit) and (other.page_view == self.page_view) and (
37
- other.count == self.count) and (other.last_timestamp == self.last_timestamp)
39
+ return (
40
+ isinstance(other, PageViewVisit)
41
+ and (other.page_view == self.page_view)
42
+ and (other.count == self.count)
43
+ and (other.last_timestamp == self.last_timestamp)
44
+ )
38
45
 
39
46
  def __str__(self):
40
47
  return (
@@ -174,7 +174,12 @@ class Visitor:
174
174
  @mapping_identifier.setter
175
175
  def mapping_identifier(self, value: str):
176
176
  """Sets the mapping identifier for this Visitor."""
177
- self._data.mapping_identifier = value
177
+ if self._data.mapping_identifier:
178
+ return
179
+ with self._data.lock:
180
+ if self._data.mapping_identifier:
181
+ return
182
+ self._data.mapping_identifier = value
178
183
  KameleoonLogger.debug("CALL/RETURN: Visitor.mapping_identifier <- (mapping_identifier: %s)", value)
179
184
 
180
185
  @property
@@ -23,6 +23,11 @@ class StringUtils:
23
23
  hidden_length = max(length - vis_count, vis_count)
24
24
  return secret[:length - hidden_length] + hid_ch * hidden_length
25
25
 
26
+ @staticmethod
27
+ def bool_to_string_lower_case(data: bool) -> str:
28
+ """Convert a boolean value to a lowercase string."""
29
+ return "true" if data else "false"
30
+
26
31
  @staticmethod
27
32
  def object_to_string(data: Any) -> str:
28
33
  """Convert various data types into their string representation."""
@@ -32,7 +37,7 @@ class StringUtils:
32
37
  if result is not None:
33
38
  return result
34
39
  if isinstance(data, bool):
35
- return "true" if data else "false"
40
+ return StringUtils.bool_to_string_lower_case(data)
36
41
  if data is None:
37
42
  return "None"
38
43
  if hasattr(data, '__str__'):
@@ -2,21 +2,24 @@
2
2
  import time
3
3
  from typing import Dict, Optional
4
4
  from kameleoon.data.manager.assigned_variation import AssignedVariation
5
+ from kameleoon.helpers.string_utils import StringUtils
5
6
  from kameleoon.hybrid.hybrid_manager import HybridManager
6
7
  from kameleoon.logging.kameleoon_logger import KameleoonLogger
8
+ from kameleoon.managers.data.data_manager import DataManager
7
9
 
8
10
 
9
11
  class HybridManagerImpl(HybridManager):
10
12
  """Implementation of HybridManager that generates tracking code for engine integration."""
11
13
  TC_INIT = "window.kameleoonQueue=window.kameleoonQueue||[];"
12
- TC_ASSIGN_VARIATION_F = "window.kameleoonQueue.push(['Experiments.assignVariation',{0},{1}]);"
13
- TC_TRIGGER_F = "window.kameleoonQueue.push(['Experiments.trigger',{0},true]);"
14
+ TC_ASSIGN_VARIATION_F = "window.kameleoonQueue.push(['Experiments.assignVariation',{0},{1},true]);"
15
+ TC_TRIGGER_F = "window.kameleoonQueue.push(['Experiments.trigger',{0},{2}]);"
14
16
  TC_ASSIGN_VARIATION_TRIGGER_F = TC_ASSIGN_VARIATION_F + TC_TRIGGER_F
15
17
 
16
- def __init__(self, expiration_period: float) -> None:
18
+ def __init__(self, expiration_period: float, data_manager: DataManager) -> None:
17
19
  KameleoonLogger.debug("CALL: HybridManagerImpl(expiration_period: %s)", expiration_period)
18
20
  super().__init__()
19
21
  self._expiration_period = expiration_period
22
+ self._data_manager = data_manager
20
23
  KameleoonLogger.debug("RETURN: HybridManagerImpl(expiration_period: %s)", expiration_period)
21
24
 
22
25
  def get_engine_tracking_code(self, visitor_variations: Optional[Dict[int, AssignedVariation]]) -> str:
@@ -27,7 +30,11 @@ class HybridManagerImpl(HybridManager):
27
30
  expiration_time = time.time() - self._expiration_period
28
31
  for variation in visitor_variations.values():
29
32
  if variation.assignment_time > expiration_time:
30
- line = self.TC_ASSIGN_VARIATION_TRIGGER_F.format(variation.experiment_id, variation.variation_id)
33
+ tracking_only = not (self._data_manager.data_file.
34
+ has_experiment_js_css_variable(variation.experiment_id))
35
+ line = self.TC_ASSIGN_VARIATION_TRIGGER_F.format(
36
+ variation.experiment_id, variation.variation_id,
37
+ StringUtils.bool_to_string_lower_case(tracking_only))
31
38
  lines.append(line)
32
39
  tracking_code = "".join(lines)
33
40
  KameleoonLogger.debug(
@@ -128,7 +128,7 @@ class KameleoonClient:
128
128
  self._visitor_manager = VisitorManager(
129
129
  self._data_manager, config.session_duration_second, self._async_executor.scheduler
130
130
  )
131
- self._hybrid_manager = HybridManagerImpl(HYBRID_EXPIRATION_TIME)
131
+ self._hybrid_manager = HybridManagerImpl(HYBRID_EXPIRATION_TIME, self._data_manager)
132
132
 
133
133
  self._cookie_manager = CookieManager(self._data_manager, config.top_level_domain)
134
134
  atsf = AccessTokenSourceFactory(config.client_id, config.client_secret)
@@ -424,7 +424,7 @@ class KameleoonClient:
424
424
  visitor_code, is_unique_identifier, instant)
425
425
 
426
426
  def is_feature_active(
427
- self, visitor_code: str, feature_key: str, is_unique_identifier: Optional[bool] = None
427
+ self, visitor_code: str, feature_key: str, is_unique_identifier: Optional[bool] = None, track=True
428
428
  ) -> bool:
429
429
  """
430
430
  Check if feature is active for a given visitor code
@@ -437,7 +437,6 @@ class KameleoonClient:
437
437
  You have to make sure that proper error handling is set up in your code as shown in the example to the right
438
438
  to catch potential exceptions.
439
439
 
440
-
441
440
  :param visitor_code: Unique identifier of the user. This field is mandatory.
442
441
  :type visitor_code: str
443
442
  :param feature_key: Key of the feature flag you want to expose to a user. This field is mandatory.
@@ -445,18 +444,18 @@ class KameleoonClient:
445
444
  :param is_unique_identifier: (Deprecated) Parameter that specifies whether the visitorCode is
446
445
  a unique identifier.
447
446
  :type is_unique_identifier: Optional[bool]
447
+ :param track: Optional flag indicating whether tracking of the feature evaluation is enabled (`True`) or
448
+ disabled (`False`); the default value is `True`.
449
+ :type track: bool
450
+
448
451
  :return: Value of the feature that is active for a given visitor_code.
449
452
  :rtype: bool
450
453
 
451
-
452
- :raises:
453
- FeatureNotFound: Exception indicating that the requested feature ID has not been found in
454
- the internal configuration of the SDK. This is usually normal and means that
455
- the feature flag has not yet been activated on Kameleoon's side
456
- (but code implementing the feature is already deployed on the
457
- web-application's side).
458
- VisitorCodeInvalid: Raise when the provided visitor code is not valid
459
- (empty, or longer than 255 characters)
454
+ :raises FeatureNotFound: Exception indicating that the requested feature ID has not been found in
455
+ the internal configuration of the SDK. This is usually normal and means that the feature flag has not yet
456
+ been activated on Kameleoon's side (but code implementing the feature is already deployed on
457
+ the web-application's side).
458
+ :raises VisitorCodeInvalid: If the visitor code is empty or longer than 255 chars.
460
459
 
461
460
  Examples:
462
461
 
@@ -476,23 +475,158 @@ class KameleoonClient:
476
475
  # Implement new checkout code here
477
476
  """
478
477
  KameleoonLogger.info(
479
- "CALL: KameleoonClient.is_feature_active(visitor_code: %s, feature_key: %s, is_unique_identifier: %s)",
480
- visitor_code, feature_key, is_unique_identifier)
478
+ "CALL: KameleoonClient.is_feature_active(visitor_code: %s, feature_key: %s, is_unique_identifier: %s, "
479
+ "track: %s)", visitor_code, feature_key, is_unique_identifier, track
480
+ )
481
481
  validate_visitor_code(visitor_code)
482
482
  if is_unique_identifier is not None:
483
483
  self.__set_unique_identifier(visitor_code, is_unique_identifier)
484
484
  try:
485
- (_, variation_key) = self.__get_feature_variation_key(visitor_code, feature_key)
485
+ feature_flag = self._data_manager.data_file.get_feature_flag(feature_key)
486
+ variation_key, _, _ = self.__get_variation_info(visitor_code, feature_flag, track)
486
487
  feature_active = variation_key != configuration.Variation.Type.OFF.value
488
+ if track:
489
+ self._tracking_manager.add_visitor_code(visitor_code)
487
490
  except FeatureEnvironmentDisabled:
488
491
  feature_active = False
489
492
  KameleoonLogger.info(
490
- "RETURN: KameleoonClient.is_feature_active(visitor_code: %s, feature_key: %s, is_unique_identifier: %s)"
491
- " -> (feature_active: %s)", visitor_code, feature_key, is_unique_identifier, feature_active)
493
+ "RETURN: KameleoonClient.is_feature_active(visitor_code: %s, feature_key: %s, is_unique_identifier: %s, "
494
+ "track: %s) -> (feature_active: %s)", visitor_code, feature_key, is_unique_identifier, feature_active, track
495
+ )
492
496
  return feature_active
493
497
 
498
+ def get_variation(self, visitor_code: str, feature_key: str, track=True) -> Variation:
499
+ """
500
+ Retrieves the variation assigned to the given visitor for a specific feature flag.
501
+
502
+ :param visitor_code: The unique identifier of the visitor.
503
+ :type visitor_code: str
504
+ :param feature_key: The unique identifier of the feature flag.
505
+ :type feature_key: str
506
+ :param track: Optional flag indicating whether tracking of the feature evaluation is enabled (`True`) or
507
+ disabled (`False`); the default value is `True`.
508
+ :type track: bool
509
+
510
+ :return: The variation assigned to the visitor if the visitor is associated with some rule of the feature flag,
511
+ otherwise the method returns the default variation of the feature flag.
512
+ :rtype: Variation
513
+
514
+ :raises VisitorCodeInvalid: If the visitor code is empty or longer than 255 chars.
515
+ :raises FeatureNotFound: Feature Flag isn't found in this configuration.
516
+ :raises FeatureEnvironmentDisabled: If the requested feature flag is disabled for the current environment.
517
+ """
518
+ KameleoonLogger.info(
519
+ "CALL: KameleoonClient.get_variation(visitor_code: '%s', feature_key: '%s', track: %s)",
520
+ visitor_code, feature_key, track
521
+ )
522
+ validate_visitor_code(visitor_code)
523
+ feature_flag = self._data_manager.data_file.get_feature_flag(feature_key)
524
+ variation_key, var_by_exp, rule = self.__get_variation_info(visitor_code, feature_flag, track)
525
+ external_variation = self.__make_external_variation(
526
+ variation_key,
527
+ feature_flag.get_variation(variation_key),
528
+ var_by_exp.variation_id if var_by_exp else None,
529
+ rule.experiment_id if rule else None
530
+ )
531
+ if track:
532
+ self._tracking_manager.add_visitor_code(visitor_code)
533
+ KameleoonLogger.info(
534
+ "RETURN: KameleoonClient.get_variation(visitor_code: '%s', feature_key: '%s', track: %s)"
535
+ " -> (variation: %s)", visitor_code, feature_key, track, external_variation
536
+ )
537
+ return external_variation
538
+
539
+ def get_variations(self, visitor_code: str, only_active=False, track=True) -> Dict[str, Variation]:
540
+ """
541
+ Forms a dictionary of variations assigned to a given visitor across all feature flags.
542
+ This method iterates over all available feature flags and returns the assigned variation for each flag
543
+ associated with the specified visitor.
544
+
545
+ :param visitor_code: The unique identifier of the visitor.
546
+ :type visitor_code: str
547
+ :param only_active: Optional flag indicating whether to return variations for active feature flags only (`True`)
548
+ or for any feature flags (`False`); the default value is `False`.
549
+ :type only_active: bool
550
+ :param track: Optional flag indicating whether tracking of the feature evaluation is enabled (`True`) or
551
+ disabled (`False`); the default value is `True`.
552
+ :type track: bool
553
+ :return: A dictionary consisting of feature flag keys as keys and
554
+ their corresponding variations (or the default variation of that feature flag) as values.
555
+ :rtype: Dict[str, Variation]
556
+
557
+ :raises VisitorCodeInvalid: If the visitor code is empty or longer than 255 chars.
558
+ """
559
+ KameleoonLogger.info(
560
+ "CALL: KameleoonClient.get_variations(visitor_code: '%s', only_active: %s, track: %s)",
561
+ visitor_code, only_active, track
562
+ )
563
+ validate_visitor_code(visitor_code)
564
+ variations: Dict[str, Variation] = {}
565
+ for feature_flag in self._data_manager.data_file.feature_flags.values():
566
+ if not feature_flag.environment_enabled:
567
+ continue
568
+ variation_key, var_by_exp, rule = self.__get_variation_info(visitor_code, feature_flag, track)
569
+ if only_active and (variation_key == configuration.Variation.Type.OFF.value):
570
+ continue
571
+ variations[feature_flag.feature_key] = self.__make_external_variation(
572
+ variation_key,
573
+ feature_flag.get_variation(variation_key),
574
+ var_by_exp.variation_id if var_by_exp else None,
575
+ rule.experiment_id if rule else None
576
+ )
577
+ if track:
578
+ self._tracking_manager.add_visitor_code(visitor_code)
579
+ KameleoonLogger.info(
580
+ "RETURN: KameleoonClient.get_variations(visitor_code: '%s', only_active: %s, track: %s)"
581
+ " -> (variations: %s)", visitor_code, only_active, track, variations
582
+ )
583
+ return variations
584
+
585
+ def __get_variation_info(
586
+ self, visitor_code: str, feature_flag: FeatureFlag, track: bool
587
+ ) -> Tuple[str, Optional[VariationByExposition], Optional[Rule]]:
588
+ KameleoonLogger.debug(
589
+ "CALL: KameleoonClient.__get_variation_info(visitor_code: %s, feature_flag: %s, track: %s)",
590
+ visitor_code, feature_flag, track
591
+ )
592
+ var_by_exp, rule = self.__calculate_variation_rule_for_feature(visitor_code, feature_flag)
593
+ variation_key = self.__calculate_variation_key(var_by_exp, rule, feature_flag)
594
+ self.__save_variation(visitor_code, rule, var_by_exp, track)
595
+ KameleoonLogger.debug(
596
+ "RETURN: KameleoonClient.__get_variation_info(visitor_code: %s, feature_flag: %s, track: %s)"
597
+ " -> (variation_key: %s, variation_by_exposition: %s, rule: %s)",
598
+ visitor_code, feature_flag, track, variation_key, var_by_exp, rule
599
+ )
600
+ return variation_key, var_by_exp, rule
601
+
602
+ @staticmethod
603
+ def __make_external_variation(
604
+ variation_key: str,
605
+ internal_variation: Optional[configuration.Variation],
606
+ variation_id: Optional[int],
607
+ experiment_id: Optional[int],
608
+ ) -> Variation:
609
+ KameleoonLogger.debug(
610
+ "CALL: KameleoonClient.__make_external_variation(variation_key: %s, internal_variation: %s, "
611
+ "variation_id: %s, experiment_id: %s)",
612
+ variation_key, internal_variation, variation_id, experiment_id
613
+ )
614
+ variables: Dict[str, Variable] = {}
615
+ if internal_variation:
616
+ for variable in internal_variation.variables:
617
+ variables[variable.key] = Variable(variable.key, variable.get_type(), variable.get_value())
618
+ variation = Variation(variation_key, variation_id, experiment_id, variables)
619
+ KameleoonLogger.debug(
620
+ "RETURN: KameleoonClient.__make_external_variation(variation_key: %s, internal_variation: %s, "
621
+ "variation_id: %s, experiment_id: %s) -> (variation: %s)",
622
+ variation_key, internal_variation, variation_id, experiment_id, variation
623
+ )
624
+ return variation
625
+
494
626
  def get_feature_variation_variables(self, feature_key: str, variation_key: str) -> Dict[str, Any]:
495
627
  """
628
+ Deprecated function. Please use `get_variation(visitor_code, feature_key, False)` instead.
629
+
496
630
  Retrieve all feature variables.
497
631
  A feature variables can be changed easily via our web application.
498
632
 
@@ -520,6 +654,10 @@ class KameleoonClient:
520
654
  """
521
655
 
522
656
  # pylint: disable=no-else-raise
657
+ KameleoonLogger.info(
658
+ "Call to deprecated function `get_feature_variation_variables`. "
659
+ "Please use `get_variation(visitor_code, feature_key, False)` instead."
660
+ )
523
661
  KameleoonLogger.info(
524
662
  "CALL: KameleoonClient.get_feature_variation_variables(feature_key: %s, variation_key: %s)",
525
663
  feature_key, variation_key)
@@ -787,7 +925,7 @@ class KameleoonClient:
787
925
 
788
926
  def get_active_feature_list_for_visitor(self, visitor_code: str) -> List[str]:
789
927
  """
790
- Depreacted function. Please use `get_active_features_for_visitor` instead.
928
+ Deprecated function. Please use `get_active_features_for_visitor` instead.
791
929
  The get_active_feature_list_for_visitor method uses for obtaining a list of feature flag IDs:
792
930
  - currently targeted and active simultaneously for a visitor
793
931
 
@@ -800,8 +938,10 @@ class KameleoonClient:
800
938
  """
801
939
  KameleoonLogger.info("CALL: KameleoonClient.get_active_feature_list_for_visitor(visitor_code: %s)",
802
940
  visitor_code)
803
- KameleoonLogger.warning("Call to deprecated function `get_active_feature_list_for_visitor`. "
804
- "Please use `get_active_features` instead.")
941
+ KameleoonLogger.info(
942
+ "Call to deprecated function `get_active_feature_list_for_visitor`. "
943
+ "Please use `get_active_features` instead."
944
+ )
805
945
 
806
946
  def filter_conditions(feature_flag: FeatureFlag) -> bool:
807
947
  if not feature_flag.environment_enabled:
@@ -826,6 +966,8 @@ class KameleoonClient:
826
966
 
827
967
  def get_active_features(self, visitor_code: str) -> Dict[str, Variation]:
828
968
  """
969
+ Deprecated function. Please use `get_variations(visitor_code, True, False)` instead.
970
+
829
971
  The get_active_features method uses for obtaining a information about the active feature flags
830
972
  that are available for the visitor.
831
973
 
@@ -839,6 +981,10 @@ class KameleoonClient:
839
981
  :raises:
840
982
  VisitorCodeInvalid: Raise when the provided visitor code is not valid
841
983
  """
984
+ KameleoonLogger.info(
985
+ "Call to deprecated function `get_active_features`. "
986
+ "Please use `get_variations(visitor_code, True, False)` instead."
987
+ )
842
988
  KameleoonLogger.info("CALL: KameleoonClient.get_active_features(visitor_code: %s)", visitor_code)
843
989
  validate_visitor_code(visitor_code)
844
990
  map_active_features: Dict[str, Variation] = {}
@@ -849,16 +995,11 @@ class KameleoonClient:
849
995
  variation_key = self.__calculate_variation_key(var_by_exp, rule, feature_flag)
850
996
  if variation_key == configuration.Variation.Type.OFF.value:
851
997
  continue
852
- variation = feature_flag.get_variation(variation_key)
853
- variables: Dict[str, Variable] = {}
854
- if variation is not None:
855
- for variable in variation.variables:
856
- variables[variable.key] = Variable(variable.key, variable.get_type(), variable.get_value())
857
- map_active_features[feature_flag.feature_key] = Variation(
998
+ map_active_features[feature_flag.feature_key] = self.__make_external_variation(
858
999
  variation_key,
859
- var_by_exp.variation_id if var_by_exp is not None else None,
860
- rule.experiment_id if rule is not None else None,
861
- variables,
1000
+ feature_flag.get_variation(variation_key),
1001
+ var_by_exp.variation_id if var_by_exp else None,
1002
+ rule.experiment_id if rule else None
862
1003
  )
863
1004
  KameleoonLogger.info("RETURN: KameleoonClient.get_active_features(visitor_code: %s) -> (active_features: %s)",
864
1005
  visitor_code, map_active_features)
@@ -868,6 +1009,8 @@ class KameleoonClient:
868
1009
  self, visitor_code: str, feature_key: str, is_unique_identifier: Optional[bool] = None
869
1010
  ) -> str:
870
1011
  """
1012
+ Deprecated function. Please use `get_variation(visitor_code, feature_key, True)` instead.
1013
+
871
1014
  Returns a variation key for visitor code
872
1015
 
873
1016
  This method takes a visitor_code and feature_key as mandatory arguments and
@@ -898,6 +1041,10 @@ class KameleoonClient:
898
1041
  FeatureEnvironmentDisabled: Exception indicating that feature flag is disabled for the
899
1042
  visitor's current environment.
900
1043
  """
1044
+ KameleoonLogger.info(
1045
+ "Call to deprecated function `get_feature_variation_key`. "
1046
+ "Please use `get_variation(visitor_code, feature_key, True)` instead."
1047
+ )
901
1048
  KameleoonLogger.info(
902
1049
  "CALL: KameleoonClient.get_feature_variation_key(visitor_code: %s, feature_key: %s, "
903
1050
  "is_unique_identifier: %s)", visitor_code, feature_key, is_unique_identifier)
@@ -915,6 +1062,8 @@ class KameleoonClient:
915
1062
  self, visitor_code: str, feature_key: str, variable_key: str, is_unique_identifier: Optional[bool] = None
916
1063
  ) -> Union[bool, str, float, Dict[str, Any], List[Any], None]:
917
1064
  """
1065
+ Deprecated function. Please use `get_variation(visitor_code, feature_key, True)` instead.
1066
+
918
1067
  Retrieves a feature variable value from assigned for visitor variation
919
1068
  A feature variable can be changed easily via our web application.
920
1069
 
@@ -943,6 +1092,10 @@ class KameleoonClient:
943
1092
  FeatureEnvironmentDisabled: Exception indicating that feature flag is disabled for the
944
1093
  visitor's current environment.
945
1094
  """
1095
+ KameleoonLogger.info(
1096
+ "Call to deprecated function `get_feature_variable`. "
1097
+ "Please use `get_variation(visitor_code, feature_key, True)` instead."
1098
+ )
946
1099
  KameleoonLogger.info(
947
1100
  "CALL: KameleoonClient.get_feature_variable(visitor_code: %s, feature_key: %s, "
948
1101
  "variable_key: %s, is_unique_identifier: %s)",
@@ -1152,30 +1305,31 @@ class KameleoonClient:
1152
1305
  feature_flag = self._data_manager.data_file.get_feature_flag(feature_key)
1153
1306
  (variation, rule) = self.__calculate_variation_rule_for_feature(visitor_code, feature_flag)
1154
1307
  variation_key = self.__calculate_variation_key(variation, rule, feature_flag)
1155
- self.__assign_feature_variation(visitor_code, rule, variation)
1308
+ self.__save_variation(visitor_code, rule, variation)
1156
1309
  self._tracking_manager.add_visitor_code(visitor_code)
1157
1310
  KameleoonLogger.debug(
1158
1311
  "RETURN: KameleoonClient.__get_feature_variation_key(visitor_code: %s, feature_key: %s) -> "
1159
1312
  "(feature_flag: %s, variation_key: %s)", visitor_code, feature_key, feature_flag, variation_key)
1160
1313
  return (feature_flag, variation_key)
1161
1314
 
1162
- def __assign_feature_variation(
1163
- self, visitor_code: str, rule: Optional[Rule], variation: Optional[VariationByExposition]
1315
+ def __save_variation(
1316
+ self, visitor_code: str, rule: Optional[Rule], variation: Optional[VariationByExposition], track=True
1164
1317
  ) -> None:
1165
- if rule is None:
1318
+ if (rule is None) or (variation is None) or (rule.experiment_id is None) or (variation.variation_id is None):
1166
1319
  return
1167
1320
  KameleoonLogger.debug(
1168
- "CALL: KameleoonClient.__assign_feature_variation(visitor_code: %s, rule: %s, variation: %s)",
1169
- visitor_code, rule, variation)
1321
+ "CALL: KameleoonClient.__save_variation(visitor_code: %s, rule: %s, variation: %s, track: %s)",
1322
+ visitor_code, rule, variation, track
1323
+ )
1170
1324
  visitor = self._visitor_manager.get_or_create_visitor(visitor_code)
1171
- experiment_id = rule.experiment_id
1172
- variation_id = variation.variation_id if variation is not None else None
1173
- if experiment_id is not None and variation_id is not None:
1174
- as_variation = AssignedVariation(experiment_id, variation_id, rule.type)
1175
- visitor.assign_variation(as_variation)
1325
+ as_variation = AssignedVariation(rule.experiment_id, variation.variation_id, rule.type)
1326
+ if not track:
1327
+ as_variation.mark_as_sent()
1328
+ visitor.assign_variation(as_variation)
1176
1329
  KameleoonLogger.debug(
1177
- "RETURN: KameleoonClient.__assign_feature_variation(visitor_code: %s, rule: %s, variation: %s)",
1178
- visitor_code, rule, variation)
1330
+ "RETURN: KameleoonClient.__save_variation(visitor_code: %s, rule: %s, variation: %s, track: %s)",
1331
+ visitor_code, rule, variation, track
1332
+ )
1179
1333
 
1180
1334
  def __calculate_variation_rule_for_feature(
1181
1335
  self, visitor_code: str, feature_flag: FeatureFlag
@@ -1247,7 +1401,7 @@ class KameleoonClient:
1247
1401
  return variation_key
1248
1402
 
1249
1403
  def __set_unique_identifier(self, visitor_code: str, is_unique_identifier: bool) -> None:
1250
- KameleoonLogger.warning(
1404
+ KameleoonLogger.info(
1251
1405
  "The 'is_unique_identifier' parameter is deprecated. Please, add 'UniqueIdentifier' to a visitor instead."
1252
1406
  )
1253
1407
  self._visitor_manager.add_data(visitor_code, UniqueIdentifier(is_unique_identifier))
@@ -1,8 +1,6 @@
1
1
  """Remote data"""
2
2
  from typing import Optional, Any, List
3
- from kameleoon.configuration.custom_data_info import CustomDataInfo
4
3
  from kameleoon.data import Data
5
- from kameleoon.data.data import BaseData
6
4
  from kameleoon.data.manager.visitor_manager import VisitorManager
7
5
  from kameleoon.logging.kameleoon_logger import KameleoonLogger
8
6
  from kameleoon.managers.data.data_manager import DataManager
@@ -53,33 +51,35 @@ class RemoteDataManager:
53
51
  data_filter = RemoteVisitorDataFilter()
54
52
  service: DataService = self._network_manager.get_service(DataService)
55
53
  response = await service.get_remote_visitor_data(visitor_code, data_filter, is_unique_identifier, timeout)
56
- visitor_data = self.__handle_remote_visitor_data_response(response, visitor_code, add_data)
54
+ visitor_data = self.__handle_remote_visitor_data_response(response, visitor_code, add_data, data_filter)
57
55
  KameleoonLogger.debug(
58
56
  "CALL: RemoteDataManager.get_visitor_data(visitor_code: %s, add_data: %s, data_filter: %s, timeout: %s) "
59
57
  "-> (visitor_data: %s)", visitor_code, add_data, data_filter, timeout, visitor_data)
60
58
  return visitor_data
61
59
 
62
60
  def __handle_remote_visitor_data_response(
63
- self, response: Response, visitor_code: str, add_data: bool
61
+ self, response: Response, visitor_code: str, add_data: bool, data_filter: RemoteVisitorDataFilter
64
62
  ) -> List[Data]:
65
63
  if response.content is None:
66
64
  return []
67
65
  custom_data_info = self._data_manager.data_file.custom_data_info
68
- data_to_add, data_to_return = RemoteDataManager.__parse_remote_visitor_data(custom_data_info, response.content)
66
+ remote_visitor_data = RemoteDataManager.__parse_remote_visitor_data(response.content)
67
+ remote_visitor_data.mark_data_as_sent(custom_data_info)
68
+ data_to_add = remote_visitor_data.collect_data_to_add()
69
69
  if add_data and data_to_add:
70
70
  # Cannot use `VisitorManager.add_data` because it could use remote visitor data for mapping.
71
71
  visitor = self._visitor_manager.get_or_create_visitor(visitor_code)
72
72
  visitor.add_data(*data_to_add, overwrite=False)
73
- return data_to_return
73
+ if data_filter.visitor_code and remote_visitor_data.visitor_code:
74
+ # We apply visitor code from the latest visit fetched from Data API
75
+ visitor = self._visitor_manager.get_or_create_visitor(visitor_code)
76
+ visitor.mapping_identifier = remote_visitor_data.visitor_code
77
+ return remote_visitor_data.collect_data_to_return()
74
78
 
75
79
  @staticmethod
76
- def __parse_remote_visitor_data(
77
- custom_data_info: CustomDataInfo, raw: Any
78
- ) -> tuple[List[BaseData], List[Data]]:
80
+ def __parse_remote_visitor_data(raw: Any) -> RemoteVisitorData:
79
81
  try:
80
- remote_visitor_data = RemoteVisitorData(raw)
81
- remote_visitor_data.mark_data_as_sent(custom_data_info)
82
- return remote_visitor_data.collect_data_to_add(), remote_visitor_data.collect_data_to_return()
82
+ return RemoteVisitorData(raw)
83
83
  except Exception as ex: # pylint: disable=W0703
84
84
  KameleoonLogger.error("Parsing of remote visitor data failed: %s", ex)
85
- return [], []
85
+ return RemoteVisitorData({})
@@ -38,6 +38,7 @@ class RemoteVisitorData:
38
38
  self.__experiments: Optional[Dict[int, AssignedVariation]] = None
39
39
  self.__conversions: Optional[List[Conversion]] = None
40
40
  self.__previous_visitor_visits: Optional[VisitorVisits] = None
41
+ self.__visitor_code: Optional[str] = None
41
42
  current_visit = json.get("currentVisit")
42
43
  if current_visit is not None:
43
44
  self.__parse_visit(current_visit)
@@ -100,7 +101,14 @@ class RemoteVisitorData:
100
101
  for conversion in self.__conversions:
101
102
  conversion.mark_as_sent()
102
103
 
104
+ @property
105
+ def visitor_code(self) -> Optional[str]:
106
+ """Returns the `visitorCode` from the most recent visit"""
107
+ return self.__visitor_code
108
+
103
109
  def __parse_visit(self, json_visit: Dict[str, Any]) -> None:
110
+ if (self.__visitor_code is None) and isinstance(visitor_code := json_visit.get("visitorCode"), str):
111
+ self.__visitor_code = visitor_code
104
112
  custom_data_events = json_visit.get("customDataEvents")
105
113
  if custom_data_events:
106
114
  self.__parse_custom_data(custom_data_events)