kameleoon-client-python 3.19.0__tar.gz → 3.22.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 (207) hide show
  1. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/PKG-INFO +14 -14
  2. kameleoon_client_python-3.22.0/kameleoon/client_readiness/async_readiness.py +43 -0
  3. kameleoon_client_python-3.22.0/kameleoon/client_readiness/threading_readiness.py +134 -0
  4. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/conversion.py +25 -1
  5. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/assigned_variation.py +7 -4
  6. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/page_view_visit.py +3 -3
  7. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/visitor.py +46 -44
  8. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/visitor_manager.py +10 -7
  9. kameleoon_client_python-3.22.0/kameleoon/data/personalization.py +44 -0
  10. kameleoon_client_python-3.22.0/kameleoon/events/__init__.py +19 -0
  11. kameleoon_client_python-3.22.0/kameleoon/events/data_file_update_event.py +33 -0
  12. kameleoon_client_python-3.22.0/kameleoon/events/data_file_update_handler.py +23 -0
  13. kameleoon_client_python-3.22.0/kameleoon/events/event_handler.py +13 -0
  14. kameleoon_client_python-3.22.0/kameleoon/events/event_manager.py +62 -0
  15. kameleoon_client_python-3.22.0/kameleoon/events/event_type.py +70 -0
  16. kameleoon_client_python-3.22.0/kameleoon/events/http_request_failure.py +70 -0
  17. kameleoon_client_python-3.22.0/kameleoon/events/http_request_handler.py +43 -0
  18. kameleoon_client_python-3.22.0/kameleoon/events/request_type.py +21 -0
  19. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/exceptions.py +18 -0
  20. kameleoon_client_python-3.22.0/kameleoon/helpers/time.py +24 -0
  21. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/hybrid/hybrid_manager_impl.py +22 -13
  22. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/kameleoon_client.py +171 -49
  23. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/kameleoon_client_config.py +12 -11
  24. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/remote_data/remote_visitor_data.py +13 -6
  25. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/network_manager.py +6 -0
  26. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/network_manager_factory.py +2 -0
  27. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/network_manager_factory_impl.py +3 -2
  28. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/network_manager_impl.py +7 -0
  29. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/automation_service_impl.py +2 -1
  30. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/configuration_service_impl.py +4 -1
  31. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/data_service_impl.py +5 -3
  32. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/service_impl.py +43 -5
  33. kameleoon_client_python-3.19.0/kameleoon/real_time/real_time_configuration_service.py → kameleoon_client_python-3.22.0/kameleoon/real_time/real_time_event_service.py +27 -18
  34. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/sdk_version.py +1 -1
  35. kameleoon_client_python-3.22.0/kameleoon/targeting/conditions/conversion_condition.py +37 -0
  36. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/exclusive_experiment_condition.py +23 -12
  37. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/target_experiment_condition.py +11 -5
  38. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +30 -20
  39. kameleoon_client_python-3.22.0/kameleoon/targeting/conditions/target_personalization_condition.py +30 -0
  40. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +2 -2
  41. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/unknown_condition.py +3 -3
  42. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +2 -3
  43. kameleoon_client_python-3.22.0/kameleoon/targeting/conditions/visitor_scope_condition.py +56 -0
  44. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/targeting_manager.py +31 -9
  45. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon_client_python.egg-info/PKG-INFO +14 -14
  46. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon_client_python.egg-info/SOURCES.txt +12 -1
  47. kameleoon_client_python-3.19.0/kameleoon/client_readiness/async_readiness.py +0 -48
  48. kameleoon_client_python-3.19.0/kameleoon/client_readiness/threading_readiness.py +0 -44
  49. kameleoon_client_python-3.19.0/kameleoon/data/personalization.py +0 -30
  50. kameleoon_client_python-3.19.0/kameleoon/targeting/conditions/conversion_condition.py +0 -24
  51. kameleoon_client_python-3.19.0/kameleoon/targeting/conditions/target_personalization_condition.py +0 -23
  52. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/MANIFEST.in +0 -0
  53. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/README.md +0 -0
  54. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/__init__.py +0 -0
  55. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/client_readiness/__init__.py +0 -0
  56. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/__init__.py +0 -0
  57. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/consent_blocking_behaviour.py +0 -0
  58. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/custom_data_info.py +0 -0
  59. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/data_file.py +0 -0
  60. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/experiment.py +0 -0
  61. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/feature_flag.py +0 -0
  62. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/me_group.py +0 -0
  63. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/rule.py +0 -0
  64. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/rule_type.py +0 -0
  65. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/settings.py +0 -0
  66. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/variable.py +0 -0
  67. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/variation.py +0 -0
  68. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/configuration/variation_by_exposition.py +0 -0
  69. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/__init__.py +0 -0
  70. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/application_version.py +0 -0
  71. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/browser.py +0 -0
  72. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/cbscores.py +0 -0
  73. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/cookie.py +0 -0
  74. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/custom_data.py +0 -0
  75. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/data.py +0 -0
  76. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/device.py +0 -0
  77. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/geolocation.py +0 -0
  78. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/kcs_heat.py +0 -0
  79. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/__init__.py +0 -0
  80. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/forced_experiment_variation.py +0 -0
  81. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/forced_feature_variation.py +0 -0
  82. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/forced_variation.py +0 -0
  83. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/legal_consent.py +0 -0
  84. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/manager/visitor_slot.py +0 -0
  85. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/mapping_identifier.py +0 -0
  86. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/operating_system.py +0 -0
  87. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/page_view.py +0 -0
  88. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/targeted_segment.py +0 -0
  89. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/unique_identifier.py +0 -0
  90. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/user_agent.py +0 -0
  91. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/data/visitor_visits.py +0 -0
  92. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/defaults.py +0 -0
  93. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/__init__.py +0 -0
  94. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/domain.py +0 -0
  95. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/functions.py +0 -0
  96. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/hasher.py +0 -0
  97. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/logger.py +0 -0
  98. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/multi_threading.py +0 -0
  99. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/nonce.py +0 -0
  100. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/repeat_timer.py +0 -0
  101. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/scheduler.py +0 -0
  102. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/sem_version.py +0 -0
  103. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/string_utils.py +0 -0
  104. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/helpers/visitor_code.py +0 -0
  105. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/hybrid/__init__.py +0 -0
  106. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/hybrid/hybrid_manager.py +0 -0
  107. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/kameleoon_client_factory.py +0 -0
  108. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/logging/__init__.py +0 -0
  109. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/logging/kameleoon_logger.py +0 -0
  110. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/logging/log_level.py +0 -0
  111. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/logging/logger.py +0 -0
  112. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/__init__.py +0 -0
  113. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/asyncexec/__init__.py +0 -0
  114. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/asyncexec/async_executor.py +0 -0
  115. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/data/__init__.py +0 -0
  116. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/data/data_manager.py +0 -0
  117. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/evaluation/__init__.py +0 -0
  118. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/evaluation/evaluated_experiment.py +0 -0
  119. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/remote_data/__init__.py +0 -0
  120. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/remote_data/remote_data_manager.py +0 -0
  121. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/tracking/__init__.py +0 -0
  122. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/tracking/tracking_builder.py +0 -0
  123. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/tracking/tracking_manager.py +0 -0
  124. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/tracking/visitor_tracking_registry.py +0 -0
  125. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/warehouse/__init__.py +0 -0
  126. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/managers/warehouse/warehouse_manager.py +0 -0
  127. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/middleware.py +0 -0
  128. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/__init__.py +0 -0
  129. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/access_token_source.py +0 -0
  130. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/access_token_source_factory.py +0 -0
  131. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/activity_event.py +0 -0
  132. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/cookie/__init__.py +0 -0
  133. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/cookie/cookie_manager.py +0 -0
  134. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/net_provider.py +0 -0
  135. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/net_provider_impl.py +0 -0
  136. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/query_builder.py +0 -0
  137. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/query_encodable.py +0 -0
  138. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/sendable.py +0 -0
  139. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/service_initialize_context.py +0 -0
  140. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/service_initialize_context_impl.py +0 -0
  141. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/__init__.py +0 -0
  142. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/automation_service.py +0 -0
  143. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/configuration_service.py +0 -0
  144. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/data_service.py +0 -0
  145. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/services/service.py +0 -0
  146. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/uri_helper.py +0 -0
  147. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/network/url_provider.py +0 -0
  148. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/real_time/__init__.py +0 -0
  149. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/real_time/real_time_event.py +0 -0
  150. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/storage/__init__.py +0 -0
  151. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/storage/cache.py +0 -0
  152. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/storage/cache_factory.py +0 -0
  153. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/storage/cache_factory_impl.py +0 -0
  154. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/storage/cache_impl.py +0 -0
  155. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/__init__.py +0 -0
  156. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/__init__.py +0 -0
  157. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/browser_condition.py +0 -0
  158. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/constants.py +0 -0
  159. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/cookie_condition.py +0 -0
  160. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/custom_datum.py +0 -0
  161. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/device_condition.py +0 -0
  162. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/geolocation_condition.py +0 -0
  163. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
  164. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/number_condition.py +0 -0
  165. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/operating_system_condition.py +0 -0
  166. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/page_title_condition.py +0 -0
  167. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/page_url_condition.py +0 -0
  168. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
  169. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
  170. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/sdk_language_condition.py +0 -0
  171. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/segment_condition.py +0 -0
  172. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/string_value_condition.py +0 -0
  173. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/targeting_condition.py +0 -0
  174. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/version_condition.py +0 -0
  175. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
  176. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
  177. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +0 -0
  178. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/models.py +0 -0
  179. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/tree_builder.py +0 -0
  180. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/targeting/tree_condition_factory.py +0 -0
  181. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/__init__.py +0 -0
  182. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/data_file.py +0 -0
  183. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/feature_flag.py +0 -0
  184. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/remote_visitor_data_filter.py +0 -0
  185. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/rule.py +0 -0
  186. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/variable.py +0 -0
  187. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon/types/variation.py +0 -0
  188. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
  189. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon_client_python.egg-info/requires.txt +13 -13
  190. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
  191. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/setup.cfg +0 -0
  192. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/setup.py +0 -0
  193. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/__init__.py +0 -0
  194. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/__init__.py +0 -0
  195. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
  196. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
  197. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/migrations/__init__.py +0 -0
  198. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
  199. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
  200. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
  201. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/manage.py +0 -0
  202. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/proj/__init__.py +0 -0
  203. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/proj/asgi.py +0 -0
  204. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/proj/settings.py +0 -0
  205. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/proj/urls.py +0 -0
  206. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/integration/proj/proj/wsgi.py +0 -0
  207. {kameleoon_client_python-3.19.0 → kameleoon_client_python-3.22.0}/tests/resources/config.yml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kameleoon-client-python
3
- Version: 3.19.0
3
+ Version: 3.22.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
@@ -20,26 +20,26 @@ Requires-Dist: requests<3.0.0,>=2.25
20
20
  Requires-Dist: sseclient-py<1.9.0,>=1.7.0
21
21
  Requires-Dist: aiohttp<4.0.0,>=3.8.0
22
22
  Provides-Extra: test
23
- Requires-Dist: wheel==0.36.2; extra == "test"
24
- Requires-Dist: Werkzeug==2.0.1; extra == "test"
25
- Requires-Dist: aiohttp<4.0.0,>=3.8.0; extra == "test"
26
- Requires-Dist: pylint==2.12.*; extra == "test"
27
23
  Requires-Dist: types-requests==2.25.0; extra == "test"
28
- Requires-Dist: pytest-asyncio==0.21.*; extra == "test"
24
+ Requires-Dist: Django==3.2.4; extra == "test"
29
25
  Requires-Dist: sseclient-py<1.9.0,>=1.7.0; extra == "test"
30
- Requires-Dist: pytest-cov==2.12.1; extra == "test"
31
- Requires-Dist: types-python-dateutil==2.8.2; extra == "test"
32
- Requires-Dist: freezegun==1.1.0; extra == "test"
33
- Requires-Dist: pyyaml<6.1.0,>=5.4.0; extra == "test"
34
26
  Requires-Dist: pytest-django==4.4.0; extra == "test"
27
+ Requires-Dist: pytest-pythonpath==0.7.3; extra == "test"
35
28
  Requires-Dist: pytest-ordering==0.6; extra == "test"
36
- Requires-Dist: Django==3.2.4; extra == "test"
37
- Requires-Dist: types-PyYAML==5.4.3; extra == "test"
29
+ Requires-Dist: aiohttp<4.0.0,>=3.8.0; extra == "test"
38
30
  Requires-Dist: flake8==4.0.1; extra == "test"
39
- Requires-Dist: pytest-pythonpath==0.7.3; extra == "test"
31
+ Requires-Dist: pytest-asyncio==0.21.*; extra == "test"
32
+ Requires-Dist: pytest-cov==2.12.1; extra == "test"
40
33
  Requires-Dist: mypy==0.991; extra == "test"
41
- Requires-Dist: requests<3.0.0,>=2.25; extra == "test"
34
+ Requires-Dist: pylint==2.12.*; extra == "test"
35
+ Requires-Dist: Werkzeug==2.0.1; extra == "test"
36
+ Requires-Dist: pyyaml<6.1.0,>=5.4.0; extra == "test"
37
+ Requires-Dist: freezegun==1.1.0; extra == "test"
42
38
  Requires-Dist: twine==3.4.1; extra == "test"
39
+ Requires-Dist: types-PyYAML==5.4.3; extra == "test"
40
+ Requires-Dist: requests<3.0.0,>=2.25; extra == "test"
41
+ Requires-Dist: wheel==0.36.2; extra == "test"
42
+ Requires-Dist: types-python-dateutil==2.8.2; extra == "test"
43
43
  Requires-Dist: aioresponses==0.7.*; extra == "test"
44
44
  Dynamic: author
45
45
  Dynamic: author-email
@@ -0,0 +1,43 @@
1
+ "Async Client Readiness"
2
+
3
+ import asyncio
4
+ from typing import Optional
5
+
6
+ from kameleoon.exceptions import Initialization
7
+ from kameleoon.client_readiness.threading_readiness import ThreadingClientReadiness
8
+
9
+
10
+ class AsyncClientReadiness:
11
+ """
12
+ A class that provides an asynchronous interface for checking client readiness.
13
+
14
+ This class wraps around a `ThreadingClientReadiness` object to provide asynchronous
15
+ methods for waiting for the client to be ready. Blocking waits are run in the
16
+ event loop's default executor so the loop is never blocked.
17
+ """
18
+
19
+ def __init__(self, inner: ThreadingClientReadiness) -> None:
20
+ """
21
+ Initializes an AsyncClientReadiness instance.
22
+ """
23
+ super().__init__()
24
+ self._inner = inner
25
+
26
+ @property
27
+ def inner(self) -> ThreadingClientReadiness:
28
+ """
29
+ Returns the inner ThreadingClientReadiness instance.
30
+ """
31
+ return self._inner
32
+
33
+ async def wait_with_timeout(self, timeout_second: float) -> Optional[Initialization]:
34
+ """
35
+ Asynchronously waits until the readiness state is settled, but no longer than
36
+ `timeout_second`. See `ThreadingClientReadiness.wait_with_timeout` for the
37
+ detailed contract.
38
+ """
39
+ # Non-blocking paths (already settled or expired timeout) are served inline.
40
+ if timeout_second <= 0:
41
+ return self._inner.wait_with_timeout(timeout_second)
42
+ loop = asyncio.get_event_loop()
43
+ return await loop.run_in_executor(None, self._inner.wait_with_timeout, timeout_second)
@@ -0,0 +1,134 @@
1
+ """ThreadingClientReadiness"""
2
+ from threading import Event, Lock
3
+ from typing import Optional
4
+
5
+ from kameleoon.exceptions import Initialization
6
+
7
+
8
+ class _State:
9
+ """
10
+ A single settlement of the readiness state: `error` is written at most once,
11
+ before the event is set, and never changes afterwards, so a waiter which
12
+ obtained the state observes exactly the outcome it was registered for.
13
+ """
14
+
15
+ def __init__(self) -> None:
16
+ self._event = Event()
17
+ self.error: Optional[Initialization] = None
18
+
19
+ def settle(self) -> None:
20
+ """Settles the state, releasing all its waiters."""
21
+ self._event.set()
22
+
23
+ @property
24
+ def settled(self) -> bool:
25
+ """Returns whether the state is settled."""
26
+ return self._event.is_set()
27
+
28
+ def wait(self, timeout_second: float) -> bool:
29
+ """Returns whether the state was settled before the timeout elapsed."""
30
+ return self._event.wait(timeout_second)
31
+
32
+
33
+ class ThreadingClientReadiness:
34
+ """
35
+ ThreadingClientReadiness tracks whether the SDK has successfully loaded its
36
+ configuration and exposes that state to `KameleoonClient.wait_init` and
37
+ `KameleoonClient.is_ready`:
38
+ - a successful fetch settles the state successfully;
39
+ - a failed fetch settles it with an `Initialization` error.
40
+
41
+ Readiness is monotonic: once the SDK is ready it stays ready, and a later failed
42
+ fetch can never revert it. A failure reported before the first success does not
43
+ prevent a subsequent successful retry from marking the SDK ready.
44
+
45
+ It is created on the thread that builds the client but settled from the
46
+ background thread(s) performing configuration fetches.
47
+ """
48
+
49
+ def __init__(self, site_code: str, environment: Optional[str]) -> None:
50
+ self._lock = Lock()
51
+ self._state = _State()
52
+ self._ready = False
53
+ self._site_code = site_code
54
+ self._environment = environment
55
+
56
+ @property
57
+ def ready(self) -> bool:
58
+ """
59
+ Returns `True` if the SDK has been successfully initialized, `False` otherwise
60
+ (including while the initialization is still pending or has failed).
61
+ It never blocks.
62
+
63
+ This is the per-request hot path, so it is lock-free: `_ready` is only ever
64
+ flipped False -> True (readiness is monotonic), making a plain attribute read
65
+ safe. At worst a reader briefly observes `False` while `mark_ready` is
66
+ completing, which is indistinguishable from calling a moment earlier.
67
+ """
68
+ return self._ready
69
+
70
+ def mark_ready(self) -> None:
71
+ """Marks the SDK ready and releases all waiters."""
72
+ with self._lock:
73
+ self._ready = True
74
+ if self._state.settled:
75
+ if self._state.error is not None:
76
+ # Recovery after a failure: the failed state is left settled for its
77
+ # waiters, and a fresh, ready state is published for the new ones.
78
+ state = _State()
79
+ state.settle()
80
+ self._state = state
81
+ else:
82
+ self._state.settle()
83
+
84
+ def mark_not_ready(self, cause: Exception) -> None:
85
+ """
86
+ Reports a failed fetch with an `Initialization` error, but only while the SDK
87
+ is not yet ready. A failure never reverts an already-ready client and is
88
+ reported at most once, so the first reported cause is the one waiters observe.
89
+
90
+ :param cause: the failure which prevented the SDK from loading its configuration.
91
+ :type cause: Exception
92
+ """
93
+ with self._lock:
94
+ if not self._state.settled:
95
+ self._state.error = Initialization(self._site_code, self._environment, cause)
96
+ self._state.settle()
97
+ # else: already ready, or the failure was already reported
98
+
99
+ def wait_with_timeout(self, timeout_second: float) -> Optional[Initialization]:
100
+ """
101
+ Blocks until the readiness state is settled, but no longer than `timeout_second`.
102
+ Returns the result of the configuration fetch: `None` once the SDK is ready, or
103
+ the `Initialization` error the fetch failure was reported with (fail-fast - it
104
+ does not wait for background retries). If no fetch result is available within
105
+ the timeout, returns an `Initialization` error caused by the expired timeout.
106
+ A non-positive timeout expires immediately unless a result is already available.
107
+ An expired timeout does not settle the readiness state: once the SDK becomes
108
+ ready, a subsequent call returns `None`.
109
+
110
+ :param timeout_second: maximum number of seconds to wait.
111
+ :type timeout_second: float
112
+ :return: `None` if the SDK is ready, otherwise an `Initialization` error.
113
+ :rtype: Optional[Initialization]
114
+ """
115
+ state = self._current_state()
116
+ if state.settled:
117
+ return state.error
118
+ if timeout_second <= 0:
119
+ return self._timeout_failure(timeout_second)
120
+ if state.wait(timeout_second):
121
+ return state.error
122
+ return self._timeout_failure(timeout_second)
123
+
124
+ def _timeout_failure(self, timeout_second: float) -> Initialization:
125
+ # The timeout failure wraps a `TimeoutError` cause (the counterpart of the
126
+ # timeout error types the other SDKs report), so a caller can distinguish an
127
+ # expired timeout from a failed fetch.
128
+ cause = TimeoutError(f"initialization did not complete within {round(timeout_second * 1000)} ms")
129
+ return Initialization(self._site_code, self._environment, cause)
130
+
131
+ def _current_state(self) -> _State:
132
+ # Synchronized for safe publication of the state swapped in by a recovery.
133
+ with self._lock:
134
+ return self._state
@@ -6,6 +6,7 @@ from typing import Optional, Iterable
6
6
  from kameleoon.data.custom_data import CustomData
7
7
  from kameleoon.data.data import Data, DataType
8
8
  from kameleoon.helpers.string_utils import StringUtils
9
+ from kameleoon.helpers.time import time_ms
9
10
  from kameleoon.network.sendable import DuplicationSafeSendableBase
10
11
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
11
12
 
@@ -45,6 +46,23 @@ class Conversion(Data, DuplicationSafeSendableBase):
45
46
  self.__revenue = revenue
46
47
  self.__negative = negative
47
48
  self._metadata = metadata
49
+ self._assignment_time_ms = time_ms()
50
+
51
+ # pylint: disable=too-many-arguments
52
+ @classmethod
53
+ def _build_internal(
54
+ cls,
55
+ goal_id: int,
56
+ revenue: float = 0.0,
57
+ negative: bool = False,
58
+ metadata: Optional[Iterable[CustomData]] = None,
59
+ assignment_time: Optional[int] = None,
60
+ ) -> "Conversion":
61
+ """Create a conversion with SDK-managed internal state."""
62
+ conversion = cls(goal_id, revenue, negative, metadata)
63
+ if assignment_time:
64
+ conversion._assignment_time_ms = assignment_time
65
+ return conversion
48
66
 
49
67
  @property
50
68
  def goal_id(self) -> int:
@@ -66,6 +84,11 @@ class Conversion(Data, DuplicationSafeSendableBase):
66
84
  """Returns metadata"""
67
85
  return self._metadata
68
86
 
87
+ @property
88
+ def _assignment_time(self) -> float:
89
+ """Returns the internal time when the conversion was added."""
90
+ return self._assignment_time_ms
91
+
69
92
  @property
70
93
  def data_type(self) -> DataType:
71
94
  return DataType.CONVERSION
@@ -97,5 +120,6 @@ class Conversion(Data, DuplicationSafeSendableBase):
97
120
  f"Conversion{{goal_id:{self.__goal_id},"
98
121
  f"revenue:{self.__revenue},"
99
122
  f"negative:{self.__negative},"
100
- f"metadata:{StringUtils.object_to_string(self._metadata)}}}"
123
+ f"metadata:{StringUtils.object_to_string(self._metadata)},"
124
+ f"assignment_time:{self._assignment_time_ms}}}"
101
125
  )
@@ -1,14 +1,17 @@
1
+ # pylint: disable=duplicate-code
1
2
  """Assigned Variation"""
2
- import time
3
+
3
4
  from typing import Optional
4
5
  from kameleoon.configuration.rule_type import RuleType
5
6
  from kameleoon.data.data import BaseData, DataType
7
+ from kameleoon.helpers.time import time_ms
6
8
  from kameleoon.network.sendable import DuplicationUnsafeSendableBase
7
9
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
8
10
 
9
11
 
10
12
  class AssignedVariation(BaseData, DuplicationUnsafeSendableBase):
11
13
  """Assigned variation"""
14
+
12
15
  EVENT_TYPE = "experiment"
13
16
 
14
17
  def __init__(
@@ -22,7 +25,7 @@ class AssignedVariation(BaseData, DuplicationUnsafeSendableBase):
22
25
  self.__experiment_id = experiment_id
23
26
  self.__variation_id = variation_id
24
27
  self.__rule_type = rule_type
25
- self.__assignment_time = assignment_time or time.time()
28
+ self.__assignment_time_ms = assignment_time or time_ms()
26
29
 
27
30
  @property
28
31
  def experiment_id(self) -> int:
@@ -42,7 +45,7 @@ class AssignedVariation(BaseData, DuplicationUnsafeSendableBase):
42
45
  @property
43
46
  def assignment_time(self) -> float:
44
47
  """Returns the time when the assignment occurred."""
45
- return self.__assignment_time
48
+ return self.__assignment_time_ms
46
49
 
47
50
  @property
48
51
  def data_type(self) -> DataType:
@@ -66,6 +69,6 @@ class AssignedVariation(BaseData, DuplicationUnsafeSendableBase):
66
69
  return (
67
70
  f"AssignedVariation{{experiment_id:{self.__experiment_id},"
68
71
  f"variation_id:{self.__variation_id},"
69
- f"assignment_time:{self.__assignment_time},"
72
+ f"assignment_time:{self.__assignment_time_ms},"
70
73
  f"rule_type:{self.__rule_type}}}"
71
74
  )
@@ -1,10 +1,10 @@
1
1
  """Page view visit"""
2
2
 
3
- import time
4
3
  from typing import Optional
5
4
  from kameleoon.data import DataType
6
5
  from kameleoon.data.data import BaseData
7
6
  from kameleoon.data.page_view import PageView
7
+ from kameleoon.helpers.time import time_ms
8
8
 
9
9
 
10
10
  class PageViewVisit(BaseData):
@@ -14,13 +14,13 @@ class PageViewVisit(BaseData):
14
14
  super().__init__()
15
15
  self.page_view = page_view
16
16
  self.count = count
17
- self.last_timestamp = last_timestamp or int(time.time() * 1000)
17
+ self.last_timestamp = last_timestamp or time_ms()
18
18
 
19
19
  def overwrite(self, new_page_view: PageView) -> None:
20
20
  """Overwrites the current PageView with a new PageView and increments the visit count."""
21
21
  self.page_view = new_page_view
22
22
  self.count += 1
23
- self.last_timestamp = int(time.time() * 1000)
23
+ self.last_timestamp = time_ms()
24
24
 
25
25
  def merge(self, page_view_visit) -> None:
26
26
  """Merges the visit data from another PageViewVisit instance into this one."""
@@ -1,5 +1,4 @@
1
1
  """Visitor"""
2
- import time
3
2
 
4
3
  from threading import Lock
5
4
  from typing import Any, Callable, Optional, Dict, List, Iterator, Iterable, cast
@@ -27,6 +26,7 @@ from kameleoon.data.manager.forced_experiment_variation import ForcedExperimentV
27
26
  from kameleoon.data.manager.forced_feature_variation import ForcedFeatureVariation
28
27
  from kameleoon.data.manager.legal_consent import LegalConsent
29
28
  from kameleoon.data.manager.page_view_visit import PageViewVisit
29
+ from kameleoon.helpers.time import time_ms
30
30
  from kameleoon.logging.kameleoon_logger import KameleoonLogger
31
31
  from kameleoon.network.sendable import Sendable
32
32
 
@@ -37,6 +37,7 @@ EMPTY_LIST: List[Any] = []
37
37
 
38
38
  class Visitor: # pylint: disable=R0904
39
39
  """Visitor"""
40
+
40
41
  def __init__(self, source: Optional["Visitor"] = None) -> None:
41
42
  if source is None:
42
43
  self._data = Visitor.VisitorData()
@@ -56,108 +57,109 @@ class Visitor: # pylint: disable=R0904
56
57
 
57
58
  def enumerate_sendable_data(self) -> Iterator[Sendable]:
58
59
  """Enumerates all sendable data associated with this Visitor."""
59
- KameleoonLogger.debug('CALL: Visitor.enumerate_sendable_data()')
60
+ KameleoonLogger.debug("CALL: Visitor.enumerate_sendable_data()")
60
61
  sendable_data = self._data.enumerate_sendable_data()
61
- KameleoonLogger.debug('RETURN: Visitor.enumerate_sendable_data() -> (sendable_data)')
62
+ KameleoonLogger.debug("RETURN: Visitor.enumerate_sendable_data() -> (sendable_data)")
62
63
  return sendable_data
63
64
 
64
65
  def count_sendable_data(self) -> int:
65
66
  """Counts the number of sendable data items associated with this Visitor."""
66
- KameleoonLogger.debug('CALL: Visitor.count_sendable_data()')
67
+ KameleoonLogger.debug("CALL: Visitor.count_sendable_data()")
67
68
  count_sendable_data = self._data.count_sendable_data()
68
- KameleoonLogger.debug('RETURN: Visitor.count_sendable_data() -> (count: %s)', count_sendable_data)
69
+ KameleoonLogger.debug("RETURN: Visitor.count_sendable_data() -> (count: %s)", count_sendable_data)
69
70
  return count_sendable_data
70
71
 
71
72
  @property
72
73
  def user_agent(self) -> Optional[str]:
73
74
  """Returns the user agent string associated with this Visitor."""
74
75
  user_agent = self._data.user_agent
75
- KameleoonLogger.debug('CALL/RETURN: Visitor.user_agent -> (user_agent: %s)', user_agent)
76
+ KameleoonLogger.debug("CALL/RETURN: Visitor.user_agent -> (user_agent: %s)", user_agent)
76
77
  return user_agent
77
78
 
78
79
  @property
79
80
  def device(self) -> Optional[Device]:
80
81
  """Returns the device information associated with this Visitor."""
81
82
  device = self._data.device
82
- KameleoonLogger.debug('CALL/RETURN: Visitor.device -> (device: %s)', device)
83
+ KameleoonLogger.debug("CALL/RETURN: Visitor.device -> (device: %s)", device)
83
84
  return device
84
85
 
85
86
  @property
86
87
  def browser(self) -> Optional[Browser]:
87
88
  """Returns the browser information associated with this Visitor."""
88
89
  browser = self._data.browser
89
- KameleoonLogger.debug('CALL/RETURN: Visitor.browser -> (browser: %s)', browser)
90
+ KameleoonLogger.debug("CALL/RETURN: Visitor.browser -> (browser: %s)", browser)
90
91
  return browser
91
92
 
92
93
  @property
93
94
  def geolocation(self) -> Optional[Geolocation]:
94
95
  """Returns the geolocation information associated with this Visitor."""
95
96
  geolocation = self._data.geolocation
96
- KameleoonLogger.debug('CALL/RETURN: Visitor.geolocation -> (geolocation: %s)', geolocation)
97
+ KameleoonLogger.debug("CALL/RETURN: Visitor.geolocation -> (geolocation: %s)", geolocation)
97
98
  return geolocation
98
99
 
99
100
  @property
100
101
  def operating_system(self) -> Optional[OperatingSystem]:
101
102
  """Returns the operating system information associated with this Visitor."""
102
103
  operating_system = self._data.operating_system
103
- KameleoonLogger.debug('CALL/RETURN: Visitor.operating_system -> (operating_system: %s)', operating_system)
104
+ KameleoonLogger.debug("CALL/RETURN: Visitor.operating_system -> (operating_system: %s)", operating_system)
104
105
  return operating_system
105
106
 
106
107
  @property
107
108
  def application_version(self) -> Optional[ApplicationVersion]:
108
109
  """Returns the application version information associated with this Visitor."""
109
110
  application_version = self._data.application_version
110
- KameleoonLogger.debug('CALL/RETURN: Visitor.application_version -> (application_version: %s)',
111
- application_version)
111
+ KameleoonLogger.debug(
112
+ "CALL/RETURN: Visitor.application_version -> (application_version: %s)", application_version
113
+ )
112
114
  return application_version
113
115
 
114
116
  @property
115
117
  def cookie(self) -> Optional[Cookie]:
116
118
  """Returns the cookie information associated with this Visitor."""
117
119
  cookie = self._data.cookie
118
- KameleoonLogger.debug('CALL/RETURN: Visitor.cookie -> (cookie: %s)', cookie)
120
+ KameleoonLogger.debug("CALL/RETURN: Visitor.cookie -> (cookie: %s)", cookie)
119
121
  return cookie
120
122
 
121
123
  @property
122
124
  def custom_data(self) -> Dict[int, CustomData]:
123
125
  """Returns the custom data associated with this Visitor."""
124
126
  custom_data = EMPTY_DICT if self._data.custom_data_dict is None else self._data.custom_data_dict.copy()
125
- KameleoonLogger.debug('CALL/RETURN: Visitor.custom_data -> (custom_data: %s)', custom_data)
127
+ KameleoonLogger.debug("CALL/RETURN: Visitor.custom_data -> (custom_data: %s)", custom_data)
126
128
  return custom_data
127
129
 
128
130
  @property
129
131
  def page_view_visits(self) -> Dict[str, PageViewVisit]:
130
132
  """Returns the page view visits associated with this Visitor."""
131
133
  page_view_visits = EMPTY_DICT if self._data.page_view_visits is None else self._data.page_view_visits.copy()
132
- KameleoonLogger.debug('CALL/RETURN: Visitor.page_view_visits -> (page_view_visits: %s)', page_view_visits)
134
+ KameleoonLogger.debug("CALL/RETURN: Visitor.page_view_visits -> (page_view_visits: %s)", page_view_visits)
133
135
  return page_view_visits
134
136
 
135
137
  @property
136
138
  def conversions(self) -> List[Conversion]:
137
139
  """Returns the conversions associated with this Visitor."""
138
140
  conversions = EMPTY_LIST if self._data.conversions is None else self._data.conversions.copy()
139
- KameleoonLogger.debug('CALL/RETURN: Visitor.conversions -> (conversions: %s)', conversions)
141
+ KameleoonLogger.debug("CALL/RETURN: Visitor.conversions -> (conversions: %s)", conversions)
140
142
  return conversions
141
143
 
142
144
  @property
143
145
  def variations(self) -> Dict[int, AssignedVariation]:
144
146
  """Returns the variations associated with this Visitor."""
145
147
  variations = EMPTY_DICT if self._data.variations is None else self._data.variations.copy()
146
- KameleoonLogger.debug('CALL/RETURN: Visitor.variations -> (variations: %s)', variations)
148
+ KameleoonLogger.debug("CALL/RETURN: Visitor.variations -> (variations: %s)", variations)
147
149
  return variations
148
150
 
149
151
  @property
150
152
  def personalizations(self) -> Dict[int, Personalization]:
151
153
  """Returns the personalizations associated with this Visitor."""
152
154
  personalizations = EMPTY_DICT if self._data.personalizations is None else self._data.personalizations.copy()
153
- KameleoonLogger.debug('CALL/RETURN: Visitor.personalizations -> (personalizations: %s)', personalizations)
155
+ KameleoonLogger.debug("CALL/RETURN: Visitor.personalizations -> (personalizations: %s)", personalizations)
154
156
  return personalizations
155
157
 
156
158
  @property
157
159
  def targeted_segments(self) -> Dict[int, TargetedSegment]:
158
160
  """Returns the personalizations associated with this Visitor."""
159
161
  targeted_segments = EMPTY_DICT if self._data.targeted_segments is None else self._data.targeted_segments.copy()
160
- KameleoonLogger.debug('CALL/RETURN: Visitor.targeted_segments -> (targeted_segments: %s)', targeted_segments)
162
+ KameleoonLogger.debug("CALL/RETURN: Visitor.targeted_segments -> (targeted_segments: %s)", targeted_segments)
161
163
  return targeted_segments
162
164
 
163
165
  def get_forced_feature_variation(self, feature_key: str) -> Optional[ForcedFeatureVariation]:
@@ -165,10 +167,10 @@ class Visitor: # pylint: disable=R0904
165
167
  Returns an associated forced feature variation by its feature key if it is present.
166
168
  Otherwise returns `None`.
167
169
  """
168
- KameleoonLogger.debug('CALL: Visitor.get_forced_feature_variation(feature_key: %s)', feature_key)
170
+ KameleoonLogger.debug("CALL: Visitor.get_forced_feature_variation(feature_key: %s)", feature_key)
169
171
  ffv = self._data.simulated_variations.get(feature_key) if self._data.simulated_variations else None
170
172
  KameleoonLogger.debug(
171
- 'RETURN: Visitor.get_forced_feature_variation(feature_key: %s) -> (variation: %s)', feature_key, ffv
173
+ "RETURN: Visitor.get_forced_feature_variation(feature_key: %s) -> (variation: %s)", feature_key, ffv
172
174
  )
173
175
  return ffv
174
176
 
@@ -177,64 +179,64 @@ class Visitor: # pylint: disable=R0904
177
179
  Returns an associated forced experiment variation by its experiment id if it is present.
178
180
  Otherwise returns `None`.
179
181
  """
180
- KameleoonLogger.debug('CALL: Visitor.get_forced_experiment_variation(experiment_id: %s)', experiment_id)
182
+ KameleoonLogger.debug("CALL: Visitor.get_forced_experiment_variation(experiment_id: %s)", experiment_id)
181
183
  fev = self._data.forced_variations.get(experiment_id) if self._data.forced_variations else None
182
184
  KameleoonLogger.debug(
183
- 'RETURN: Visitor.get_forced_experiment_variation(experiment_id: %s) -> (variation: %s)', experiment_id, fev
185
+ "RETURN: Visitor.get_forced_experiment_variation(experiment_id: %s) -> (variation: %s)", experiment_id, fev
184
186
  )
185
187
  return fev
186
188
 
187
189
  def reset_forced_experiment_variation(self, experiment_id: int) -> None:
188
190
  """Resets an associated forced experiment variation for some experiment id"""
189
- KameleoonLogger.debug('CALL: Visitor.reset_forced_experiment_variation(experiment_id: %s)', experiment_id)
191
+ KameleoonLogger.debug("CALL: Visitor.reset_forced_experiment_variation(experiment_id: %s)", experiment_id)
190
192
  if self._data.forced_variations:
191
193
  self._data.forced_variations.pop(experiment_id, None)
192
- KameleoonLogger.debug('RETURN: Visitor.reset_forced_experiment_variation(experiment_id: %s)', experiment_id)
194
+ KameleoonLogger.debug("RETURN: Visitor.reset_forced_experiment_variation(experiment_id: %s)", experiment_id)
193
195
 
194
196
  def update_simulated_variations(self, variations: Iterable[ForcedFeatureVariation]) -> None:
195
197
  """Updates the associated simulated variations"""
196
198
  if not (self._data.simulated_variations or variations):
197
199
  return
198
- KameleoonLogger.debug('CALL: Visitor.update_simulated_variations(variations: %s)', variations)
200
+ KameleoonLogger.debug("CALL: Visitor.update_simulated_variations(variations: %s)", variations)
199
201
  self._data.simulated_variations = {sv.feature_key: sv for sv in variations}
200
- KameleoonLogger.debug('RETURN: Visitor.update_simulated_variations(variations: %s)', variations)
202
+ KameleoonLogger.debug("RETURN: Visitor.update_simulated_variations(variations: %s)", variations)
201
203
 
202
204
  @property
203
205
  def kcs_heat(self) -> Optional[KcsHeat]:
204
206
  """Returns the KCS heat data associated with this Visitor."""
205
207
  kcs_heat = self._data.kcs_heat
206
- KameleoonLogger.debug('CALL/RETURN: Visitor.kcs_heat -> (kcs_heat: %s)', kcs_heat)
208
+ KameleoonLogger.debug("CALL/RETURN: Visitor.kcs_heat -> (kcs_heat: %s)", kcs_heat)
207
209
  return kcs_heat
208
210
 
209
211
  @property
210
212
  def cbscores(self) -> Optional[CBScores]:
211
213
  """Returns the CBS data associated with this Visitor."""
212
214
  cbs = self._data.cbscores
213
- KameleoonLogger.debug('CALL/RETURN: Visitor.cbscores -> (cbs: %s)', cbs)
215
+ KameleoonLogger.debug("CALL/RETURN: Visitor.cbscores -> (cbs: %s)", cbs)
214
216
  return cbs
215
217
 
216
218
  @property
217
219
  def visitor_visits(self) -> Optional[VisitorVisits]:
218
220
  """Returns the visitor visits data associated with this Visitor."""
219
221
  visitor_visits = self._data.visitor_visits
220
- KameleoonLogger.debug('CALL/RETURN: Visitor.visitor_visits -> (visitor_visits: %s)', visitor_visits)
222
+ KameleoonLogger.debug("CALL/RETURN: Visitor.visitor_visits -> (visitor_visits: %s)", visitor_visits)
221
223
  return visitor_visits
222
224
 
223
225
  def assign_variation(self, variation: AssignedVariation) -> None:
224
226
  """Assigns a variation to the Visitor."""
225
- KameleoonLogger.debug('CALL: Visitor.assign_variation(variation: %s)', variation)
227
+ KameleoonLogger.debug("CALL: Visitor.assign_variation(variation: %s)", variation)
226
228
  if self._data.variations is None:
227
229
  with self._data.lock:
228
230
  if self._data.variations is None:
229
231
  self._data.variations = {variation.experiment_id: variation}
230
- KameleoonLogger.debug('RETURN: Visitor.assign_variation(variation: %s)', variation)
232
+ KameleoonLogger.debug("RETURN: Visitor.assign_variation(variation: %s)", variation)
231
233
  return
232
234
  self._data.variations[variation.experiment_id] = variation
233
- KameleoonLogger.debug('RETURN: Visitor.assign_variation(variation: %s)', variation)
235
+ KameleoonLogger.debug("RETURN: Visitor.assign_variation(variation: %s)", variation)
234
236
 
235
237
  def add_data(self, *args, overwrite: bool = True, track: bool = True) -> None:
236
238
  """Adds data to the Visitor."""
237
- KameleoonLogger.debug('CALL: Visitor.add_data(args: %s, overwrite: %s, track: %s)', args, overwrite, track)
239
+ KameleoonLogger.debug("CALL: Visitor.add_data(args: %s, overwrite: %s, track: %s)", args, overwrite, track)
238
240
  with self._data.lock:
239
241
  for data in args:
240
242
  if data is None:
@@ -247,14 +249,13 @@ class Visitor: # pylint: disable=R0904
247
249
  data_adder(self, self.DataAddingContext(data, overwrite))
248
250
  else:
249
251
  KameleoonLogger.warning("Data has unsupported type %s", data_type)
250
- KameleoonLogger.debug('RETURN: Visitor.add_data(args: %s, overwrite: %s, track: %s)', args, overwrite, track)
252
+ KameleoonLogger.debug("RETURN: Visitor.add_data(args: %s, overwrite: %s, track: %s)", args, overwrite, track)
251
253
 
252
254
  @property
253
255
  def mapping_identifier(self) -> Optional[str]:
254
256
  """Returns the mapping identifier associated with this Visitor."""
255
257
  mapping_identifier = self._data.mapping_identifier
256
- KameleoonLogger.debug('CALL/RETURN: Visitor.mapping_identifier -> (mapping_identifier: %s)',
257
- mapping_identifier)
258
+ KameleoonLogger.debug("CALL/RETURN: Visitor.mapping_identifier -> (mapping_identifier: %s)", mapping_identifier)
258
259
  return mapping_identifier
259
260
 
260
261
  @mapping_identifier.setter
@@ -272,7 +273,7 @@ class Visitor: # pylint: disable=R0904
272
273
  def legal_consent(self) -> LegalConsent:
273
274
  """Returns the legal consent status for this Visitor."""
274
275
  legal_consent = self._data.legal_consent
275
- KameleoonLogger.debug('CALL/RETURN: Visitor.legal_consent -> (legal_consent: %s)', legal_consent)
276
+ KameleoonLogger.debug("CALL/RETURN: Visitor.legal_consent -> (legal_consent: %s)", legal_consent)
276
277
  return legal_consent
277
278
 
278
279
  @legal_consent.setter
@@ -285,14 +286,16 @@ class Visitor: # pylint: disable=R0904
285
286
  def is_unique_identifier(self) -> bool:
286
287
  """Returns the unique identifier status for this Visitor."""
287
288
  is_unique_identifier = self._is_unique_identifier
288
- KameleoonLogger.debug('CALL/RETURN: Visitor.is_unique_identifier -> (is_unique_identifier: %s)',
289
- is_unique_identifier)
289
+ KameleoonLogger.debug(
290
+ "CALL/RETURN: Visitor.is_unique_identifier -> (is_unique_identifier: %s)", is_unique_identifier
291
+ )
290
292
  return is_unique_identifier
291
293
 
292
294
  class VisitorData:
293
295
  """Visitor Data"""
296
+
294
297
  def __init__(self) -> None:
295
- self.time_started = int(time.time() * 1000)
298
+ self.time_started = time_ms()
296
299
  self.lock = Lock()
297
300
  self.user_agent: Optional[str] = None
298
301
  self.device: Optional[Device] = None
@@ -365,9 +368,8 @@ class Visitor: # pylint: disable=R0904
365
368
 
366
369
  class DataAddingContext:
367
370
  """Data adding context"""
368
- def __init__(
369
- self, data: Data, overwrite: bool = True
370
- ) -> None:
371
+
372
+ def __init__(self, data: Data, overwrite: bool = True) -> None:
371
373
  self._data = data
372
374
  self._overwrite = overwrite
373
375