kameleoon-client-python 3.17.0__tar.gz → 3.18.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.
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/PKG-INFO +16 -16
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/__init__.py +2 -0
- kameleoon_client_python-3.18.0/kameleoon/data/application_version.py +39 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/data.py +1 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/visitor.py +20 -3
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/visitor_manager.py +24 -14
- kameleoon_client_python-3.18.0/kameleoon/helpers/sem_version.py +60 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/kameleoon_client.py +36 -17
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/kameleoon_client_config.py +2 -2
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/remote_data/remote_visitor_data.py +8 -10
- kameleoon_client_python-3.18.0/kameleoon/sdk_version.py +12 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/browser_condition.py +4 -2
- kameleoon_client_python-3.18.0/kameleoon/targeting/conditions/sdk_language_condition.py +38 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/targeting_condition.py +1 -0
- kameleoon_client_python-3.18.0/kameleoon/targeting/conditions/version_condition.py +61 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/targeting_manager.py +3 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/tree_condition_factory.py +4 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon_client_python.egg-info/PKG-INFO +16 -16
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon_client_python.egg-info/SOURCES.txt +3 -0
- kameleoon_client_python-3.17.0/kameleoon/sdk_version.py +0 -40
- kameleoon_client_python-3.17.0/kameleoon/targeting/conditions/sdk_language_condition.py +0 -79
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/MANIFEST.in +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/README.md +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/client_readiness/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/client_readiness/async_readiness.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/client_readiness/threading_readiness.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/consent_blocking_behaviour.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/custom_data_info.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/data_file.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/experiment.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/feature_flag.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/me_group.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/rule.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/rule_type.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/settings.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/variable.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/variation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/configuration/variation_by_exposition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/browser.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/cbscores.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/conversion.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/cookie.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/custom_data.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/device.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/geolocation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/kcs_heat.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/assigned_variation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/forced_experiment_variation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/forced_feature_variation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/forced_variation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/legal_consent.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/page_view_visit.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/visitor_slot.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/mapping_identifier.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/operating_system.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/page_view.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/personalization.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/targeted_segment.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/unique_identifier.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/user_agent.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/visitor_visits.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/defaults.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/exceptions.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/domain.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/functions.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/hasher.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/logger.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/multi_threading.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/nonce.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/repeat_timer.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/scheduler.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/string_utils.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/helpers/visitor_code.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/hybrid/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/hybrid/hybrid_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/hybrid/hybrid_manager_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/kameleoon_client_factory.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/logging/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/logging/kameleoon_logger.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/logging/log_level.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/logging/logger.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/asyncexec/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/asyncexec/async_executor.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/data/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/data/data_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/evaluation/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/evaluation/evaluated_experiment.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/remote_data/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/remote_data/remote_data_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/tracking/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/tracking/tracking_builder.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/tracking/tracking_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/tracking/visitor_tracking_registry.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/warehouse/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/managers/warehouse/warehouse_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/middleware.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/access_token_source.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/access_token_source_factory.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/activity_event.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/cookie/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/cookie/cookie_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/net_provider.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/net_provider_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/network_manager.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/network_manager_factory.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/network_manager_factory_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/network_manager_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/query_builder.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/query_encodable.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/sendable.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/service_initialize_context.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/service_initialize_context_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/automation_service.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/automation_service_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/configuration_service.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/configuration_service_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/data_service.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/data_service_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/service.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/services/service_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/uri_helper.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/network/url_provider.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/real_time/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/real_time/real_time_configuration_service.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/real_time/real_time_event.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/storage/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/storage/cache.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/storage/cache_factory.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/storage/cache_factory_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/storage/cache_impl.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/constants.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/conversion_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/cookie_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/custom_datum.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/device_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/exclusive_experiment_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/geolocation_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/number_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/operating_system_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/page_title_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/page_url_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/segment_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/string_value_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/target_experiment_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/target_personalization_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/unknown_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/models.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/targeting/tree_builder.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/types/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/types/remote_visitor_data_filter.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/types/variable.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/types/variation.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon_client_python.egg-info/requires.txt +15 -15
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/setup.cfg +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/setup.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/migrations/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/manage.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/proj/__init__.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/proj/asgi.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/proj/settings.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/proj/urls.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/tests/integration/proj/proj/wsgi.py +0 -0
- {kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.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.
|
|
3
|
+
Version: 3.18.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,27 +20,27 @@ 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: pytest-asyncio==0.21.*; extra == "test"
|
|
24
|
-
Requires-Dist: aiohttp<4.0.0,>=3.8.0; extra == "test"
|
|
25
|
-
Requires-Dist: freezegun==1.1.0; extra == "test"
|
|
26
|
-
Requires-Dist: twine==3.4.1; extra == "test"
|
|
27
|
-
Requires-Dist: wheel==0.36.2; extra == "test"
|
|
28
|
-
Requires-Dist: Werkzeug==2.0.1; extra == "test"
|
|
29
23
|
Requires-Dist: mypy==0.991; extra == "test"
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
24
|
+
Requires-Dist: flake8==4.0.1; extra == "test"
|
|
25
|
+
Requires-Dist: types-requests==2.25.0; extra == "test"
|
|
26
|
+
Requires-Dist: pytest-pythonpath==0.7.3; extra == "test"
|
|
33
27
|
Requires-Dist: aioresponses==0.7.*; extra == "test"
|
|
28
|
+
Requires-Dist: twine==3.4.1; extra == "test"
|
|
34
29
|
Requires-Dist: pytest-django==4.4.0; extra == "test"
|
|
35
30
|
Requires-Dist: Django==3.2.4; extra == "test"
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist: pyyaml<6.1.0,>=5.4.0; extra == "test"
|
|
31
|
+
Requires-Dist: pytest-cov==2.12.1; extra == "test"
|
|
32
|
+
Requires-Dist: types-python-dateutil==2.8.2; extra == "test"
|
|
39
33
|
Requires-Dist: pylint==2.12.*; extra == "test"
|
|
34
|
+
Requires-Dist: aiohttp<4.0.0,>=3.8.0; extra == "test"
|
|
35
|
+
Requires-Dist: Werkzeug==2.0.1; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-asyncio==0.21.*; extra == "test"
|
|
37
|
+
Requires-Dist: sseclient-py<1.9.0,>=1.7.0; extra == "test"
|
|
38
|
+
Requires-Dist: wheel==0.36.2; extra == "test"
|
|
40
39
|
Requires-Dist: types-PyYAML==5.4.3; extra == "test"
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist:
|
|
40
|
+
Requires-Dist: pyyaml<6.1.0,>=5.4.0; extra == "test"
|
|
41
|
+
Requires-Dist: pytest-ordering==0.6; extra == "test"
|
|
42
|
+
Requires-Dist: freezegun==1.1.0; extra == "test"
|
|
43
|
+
Requires-Dist: requests<3.0.0,>=2.25; extra == "test"
|
|
44
44
|
Dynamic: author
|
|
45
45
|
Dynamic: author-email
|
|
46
46
|
Dynamic: classifier
|
{kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/__init__.py
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
""" Imports all kameleoon data objects """
|
|
2
2
|
|
|
3
|
+
from .application_version import ApplicationVersion
|
|
3
4
|
from .browser import Browser, BrowserType
|
|
4
5
|
from .conversion import Conversion
|
|
5
6
|
from .cookie import Cookie
|
|
@@ -13,6 +14,7 @@ from .user_agent import UserAgent
|
|
|
13
14
|
from .unique_identifier import UniqueIdentifier
|
|
14
15
|
|
|
15
16
|
__all__ = [
|
|
17
|
+
"ApplicationVersion",
|
|
16
18
|
"Browser",
|
|
17
19
|
"BrowserType",
|
|
18
20
|
"Conversion",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Application version data"""
|
|
2
|
+
|
|
3
|
+
from kameleoon.data.data import Data, DataType
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ApplicationVersion(Data):
|
|
7
|
+
"""Application version data for targeting by application version.
|
|
8
|
+
|
|
9
|
+
The ApplicationVersion class represents the version of a user's application
|
|
10
|
+
and is used for targeting users based on semantic versioning (major, major.minor,
|
|
11
|
+
or major.minor.patch).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, version: str) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Creates a new ApplicationVersion.
|
|
17
|
+
|
|
18
|
+
:param version: The application version string (semantic versioning: major, major.minor, or
|
|
19
|
+
major.minor.patch). Examples: "1", "1.2", "1.2.3"
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
|
|
23
|
+
.. code-block:: python3
|
|
24
|
+
|
|
25
|
+
kameleoon_client.add_data(visitor_code, ApplicationVersion("1.2.3"))
|
|
26
|
+
"""
|
|
27
|
+
self.__version = version
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def version(self) -> str:
|
|
31
|
+
"""Returns the application version string."""
|
|
32
|
+
return self.__version
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def data_type(self) -> DataType:
|
|
36
|
+
return DataType.APPLICATION_VERSION
|
|
37
|
+
|
|
38
|
+
def __str__(self):
|
|
39
|
+
return f"ApplicationVersion{{version:{self.__version}}}"
|
{kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/data/manager/visitor.py
RENAMED
|
@@ -6,6 +6,7 @@ from typing import Any, Callable, Optional, Dict, List, Iterator, Iterable, cast
|
|
|
6
6
|
|
|
7
7
|
from kameleoon.data.visitor_visits import VisitorVisits
|
|
8
8
|
from kameleoon.data.data import Data
|
|
9
|
+
from kameleoon.data.application_version import ApplicationVersion
|
|
9
10
|
from kameleoon.data.browser import Browser
|
|
10
11
|
from kameleoon.data.cbscores import CBScores
|
|
11
12
|
from kameleoon.data.conversion import Conversion
|
|
@@ -102,6 +103,14 @@ class Visitor: # pylint: disable=R0904
|
|
|
102
103
|
KameleoonLogger.debug('CALL/RETURN: Visitor.operating_system -> (operating_system: %s)', operating_system)
|
|
103
104
|
return operating_system
|
|
104
105
|
|
|
106
|
+
@property
|
|
107
|
+
def application_version(self) -> Optional[ApplicationVersion]:
|
|
108
|
+
"""Returns the application version information associated with this Visitor."""
|
|
109
|
+
application_version = self._data.application_version
|
|
110
|
+
KameleoonLogger.debug('CALL/RETURN: Visitor.application_version -> (application_version: %s)',
|
|
111
|
+
application_version)
|
|
112
|
+
return application_version
|
|
113
|
+
|
|
105
114
|
@property
|
|
106
115
|
def cookie(self) -> Optional[Cookie]:
|
|
107
116
|
"""Returns the cookie information associated with this Visitor."""
|
|
@@ -223,20 +232,22 @@ class Visitor: # pylint: disable=R0904
|
|
|
223
232
|
self._data.variations[variation.experiment_id] = variation
|
|
224
233
|
KameleoonLogger.debug('RETURN: Visitor.assign_variation(variation: %s)', variation)
|
|
225
234
|
|
|
226
|
-
def add_data(self, *args, overwrite: bool = True) -> None:
|
|
235
|
+
def add_data(self, *args, overwrite: bool = True, track: bool = True) -> None:
|
|
227
236
|
"""Adds data to the Visitor."""
|
|
228
|
-
KameleoonLogger.debug('CALL: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
|
|
237
|
+
KameleoonLogger.debug('CALL: Visitor.add_data(args: %s, overwrite: %s, track: %s)', args, overwrite, track)
|
|
229
238
|
with self._data.lock:
|
|
230
239
|
for data in args:
|
|
231
240
|
if data is None:
|
|
232
241
|
continue
|
|
242
|
+
if not track and isinstance(data, Sendable):
|
|
243
|
+
data.mark_as_sent()
|
|
233
244
|
data_type = type(data)
|
|
234
245
|
data_adder = self.DATA_ADDERS.get(data_type)
|
|
235
246
|
if data_adder:
|
|
236
247
|
data_adder(self, self.DataAddingContext(data, overwrite))
|
|
237
248
|
else:
|
|
238
249
|
KameleoonLogger.warning("Data has unsupported type %s", data_type)
|
|
239
|
-
KameleoonLogger.debug('RETURN: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
|
|
250
|
+
KameleoonLogger.debug('RETURN: Visitor.add_data(args: %s, overwrite: %s, track: %s)', args, overwrite, track)
|
|
240
251
|
|
|
241
252
|
@property
|
|
242
253
|
def mapping_identifier(self) -> Optional[str]:
|
|
@@ -302,6 +313,7 @@ class Visitor: # pylint: disable=R0904
|
|
|
302
313
|
self.visitor_visits: Optional[VisitorVisits] = None
|
|
303
314
|
self.mapping_identifier: Optional[str] = None
|
|
304
315
|
self.legal_consent = LegalConsent.UNKNOWN
|
|
316
|
+
self.application_version: Optional[ApplicationVersion] = None
|
|
305
317
|
|
|
306
318
|
def enumerate_sendable_data(self) -> Iterator[Sendable]:
|
|
307
319
|
"""Iterates over all sendable data associated with the visitor."""
|
|
@@ -420,6 +432,10 @@ class Visitor: # pylint: disable=R0904
|
|
|
420
432
|
if context.overwrite or self._data.operating_system is None:
|
|
421
433
|
self._data.operating_system = cast(OperatingSystem, context.data)
|
|
422
434
|
|
|
435
|
+
def _set_application_version(self, context: DataAddingContext) -> None:
|
|
436
|
+
if context.overwrite or self._data.application_version is None:
|
|
437
|
+
self._data.application_version = cast(ApplicationVersion, context.data)
|
|
438
|
+
|
|
423
439
|
def _set_cookie(self, context: DataAddingContext) -> None:
|
|
424
440
|
self._data.cookie = cast(Cookie, context.data)
|
|
425
441
|
|
|
@@ -482,6 +498,7 @@ class Visitor: # pylint: disable=R0904
|
|
|
482
498
|
Browser: _set_browser,
|
|
483
499
|
Geolocation: _set_geolocation,
|
|
484
500
|
OperatingSystem: _set_operating_system,
|
|
501
|
+
ApplicationVersion: _set_application_version,
|
|
485
502
|
Cookie: _set_cookie,
|
|
486
503
|
CustomData: _add_custom_data,
|
|
487
504
|
MappingIdentifier: _add_custom_data,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Visitor Manager"""
|
|
2
|
+
|
|
2
3
|
import collections
|
|
3
4
|
import time
|
|
4
5
|
from typing import Any, Dict, Iterator, List, Optional
|
|
@@ -14,17 +15,16 @@ from kameleoon.managers.data.data_manager import DataManager
|
|
|
14
15
|
|
|
15
16
|
class VisitorManager:
|
|
16
17
|
"""Visitor manager"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
KameleoonLogger.debug("CALL: VisitorManager(data_manager, expiration_period: %s, scheduler)",
|
|
21
|
-
expiration_period)
|
|
18
|
+
|
|
19
|
+
def __init__(self, data_manager: DataManager, expiration_period: float, scheduler: Scheduler) -> None:
|
|
20
|
+
KameleoonLogger.debug("CALL: VisitorManager(data_manager, expiration_period: %s, scheduler)", expiration_period)
|
|
22
21
|
self._data_manager = data_manager
|
|
23
22
|
self.__expiration_period = expiration_period
|
|
24
23
|
self._slots: Dict[str, VisitorSlot] = collections.defaultdict(VisitorSlot)
|
|
25
24
|
scheduler.schedule_job("VisitorManager.purge", expiration_period, self.__purge)
|
|
26
|
-
KameleoonLogger.debug(
|
|
27
|
-
|
|
25
|
+
KameleoonLogger.debug(
|
|
26
|
+
"RETURN: VisitorManager(data_manager, expiration_period: %s, scheduler)", expiration_period
|
|
27
|
+
)
|
|
28
28
|
|
|
29
29
|
def __iter__(self) -> Iterator[str]:
|
|
30
30
|
yield from list(self._slots)
|
|
@@ -44,8 +44,9 @@ class VisitorManager:
|
|
|
44
44
|
visitor = slot.visitor
|
|
45
45
|
finally:
|
|
46
46
|
slot.lock.release()
|
|
47
|
-
KameleoonLogger.debug(
|
|
48
|
-
|
|
47
|
+
KameleoonLogger.debug(
|
|
48
|
+
"RETURN: VisitorManager.get_visitor(visitor_code: %s) -> (visitor: %s)", visitor_code, visitor
|
|
49
|
+
)
|
|
49
50
|
return visitor
|
|
50
51
|
|
|
51
52
|
def get_or_create_visitor(self, visitor_code: str) -> Visitor:
|
|
@@ -62,7 +63,7 @@ class VisitorManager:
|
|
|
62
63
|
slot.lock.release()
|
|
63
64
|
KameleoonLogger.debug("RETURN: VisitorManager.get_or_create_visitor(visitor_code: %s)", visitor_code)
|
|
64
65
|
|
|
65
|
-
def add_data(self, visitor_code: str, *args) -> Visitor:
|
|
66
|
+
def add_data(self, visitor_code: str, *args, track: bool = True) -> Visitor:
|
|
66
67
|
"""
|
|
67
68
|
Adds data to a visitor.
|
|
68
69
|
|
|
@@ -70,8 +71,13 @@ class VisitorManager:
|
|
|
70
71
|
* marks custom data of the local scope as unsent
|
|
71
72
|
* converts custom data with the mapping identifier index to the mapping identifier
|
|
72
73
|
* maps a visitor by its mapping identifier
|
|
74
|
+
|
|
75
|
+
:param track: A boolean indicating whether the data should be tracked (sent to server).
|
|
76
|
+
If False, sendable data will be marked as sent immediately. Default is True.
|
|
73
77
|
"""
|
|
74
|
-
KameleoonLogger.debug(
|
|
78
|
+
KameleoonLogger.debug(
|
|
79
|
+
"CALL: VisitorManager.add_data(visitor_code: %s, args: %s, track: %s)", visitor_code, args, track
|
|
80
|
+
)
|
|
75
81
|
visitor = self.get_or_create_visitor(visitor_code)
|
|
76
82
|
custom_data_info = self._data_manager.data_file.custom_data_info
|
|
77
83
|
data_to_add: List[Any] = [None] * len(args)
|
|
@@ -81,9 +87,13 @@ class VisitorManager:
|
|
|
81
87
|
elif isinstance(data, Conversion):
|
|
82
88
|
data = self.__process_conversion(data, custom_data_info)
|
|
83
89
|
data_to_add[i] = data
|
|
84
|
-
visitor.add_data(*data_to_add)
|
|
85
|
-
KameleoonLogger.debug(
|
|
86
|
-
|
|
90
|
+
visitor.add_data(*data_to_add, track=track)
|
|
91
|
+
KameleoonLogger.debug(
|
|
92
|
+
"RETURN: VisitorManager.add_data(visitor_code: %s, args: %s, track: %s) -> (visitor)",
|
|
93
|
+
visitor_code,
|
|
94
|
+
args,
|
|
95
|
+
track,
|
|
96
|
+
)
|
|
87
97
|
return visitor
|
|
88
98
|
|
|
89
99
|
def __process_custom_data(
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Version utility for parsing and comparing semantic versions"""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SemVersion:
|
|
9
|
+
"""SemVersion (Semantic versions) is a utility class for parsing and comparing semantic versions.
|
|
10
|
+
|
|
11
|
+
Supports semantic versioning with major, minor, and patch components.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def from_string(version_string: str) -> Optional["SemVersion"]:
|
|
16
|
+
"""
|
|
17
|
+
Parses a version string into a Version object.
|
|
18
|
+
|
|
19
|
+
:param version_string: The version string to parse (e.g., "1", "1.2", "1.2.3")
|
|
20
|
+
:return: Version object or None if parsing failed
|
|
21
|
+
"""
|
|
22
|
+
versions = [0, 0, 0]
|
|
23
|
+
version_parts = version_string.split(".")
|
|
24
|
+
|
|
25
|
+
for i in range(min(len(versions), len(version_parts))):
|
|
26
|
+
try:
|
|
27
|
+
versions[i] = int(version_parts[i])
|
|
28
|
+
except ValueError:
|
|
29
|
+
KameleoonLogger.error("Invalid version component, index: %s, value: %s", i, version_parts[i])
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
return SemVersion(versions[0], versions[1], versions[2])
|
|
33
|
+
|
|
34
|
+
def __init__(self, major: int = 0, minor: int = 0, patch: int = 0) -> None:
|
|
35
|
+
"""
|
|
36
|
+
Creates a new Version.
|
|
37
|
+
|
|
38
|
+
:param major: Major version number
|
|
39
|
+
:param minor: Minor version number
|
|
40
|
+
:param patch: Patch version number
|
|
41
|
+
"""
|
|
42
|
+
self.major = major
|
|
43
|
+
self.minor = minor
|
|
44
|
+
self.patch = patch
|
|
45
|
+
|
|
46
|
+
def compare_to(self, other: "SemVersion") -> int:
|
|
47
|
+
"""
|
|
48
|
+
Compares SemVersion instances
|
|
49
|
+
"""
|
|
50
|
+
a = (self.major, self.minor, self.patch)
|
|
51
|
+
b = (other.major, other.minor, other.patch)
|
|
52
|
+
return (a > b) - (a < b)
|
|
53
|
+
|
|
54
|
+
def to_float(self) -> float:
|
|
55
|
+
"""
|
|
56
|
+
Converts the version to a float (only major and minor are considered).
|
|
57
|
+
|
|
58
|
+
:return: Float representation of the version (e.g., 1.2)
|
|
59
|
+
"""
|
|
60
|
+
return float(f"{self.major}.{self.minor}")
|
{kameleoon_client_python-3.17.0 → kameleoon_client_python-3.18.0}/kameleoon/kameleoon_client.py
RENAMED
|
@@ -324,7 +324,7 @@ class KameleoonClient:
|
|
|
324
324
|
cookies,
|
|
325
325
|
)
|
|
326
326
|
|
|
327
|
-
def add_data(self, visitor_code: str, *args) -> None:
|
|
327
|
+
def add_data(self, visitor_code: str, *args, track: bool = True) -> None:
|
|
328
328
|
"""
|
|
329
329
|
To associate various data with the current user, we can use the add_data() method.
|
|
330
330
|
This method requires the visitor_code as a first parameter, and then accepts several additional parameters.
|
|
@@ -337,7 +337,9 @@ class KameleoonClient:
|
|
|
337
337
|
|
|
338
338
|
:param visitor_code: Unique identifier of the user. This field is mandatory.
|
|
339
339
|
:type visitor_code: str
|
|
340
|
-
:param args:
|
|
340
|
+
:param args: One or more Kameleoon Data objects to associate with the visitor.
|
|
341
|
+
:param track: A boolean indicating whether the data should be tracked (sent to server). Default is True.
|
|
342
|
+
:type track: bool
|
|
341
343
|
:return: None
|
|
342
344
|
|
|
343
345
|
Examples:
|
|
@@ -349,13 +351,17 @@ class KameleoonClient:
|
|
|
349
351
|
visitor_code = kameleoon_client.get_visitor_code(request.COOKIES)
|
|
350
352
|
kameleoon_client.add_data(visitor_code, CustomData("test-id", "test-value"))
|
|
351
353
|
kameleoon_client.add_data(visitor_code, Browser(BrowserType.CHROME))
|
|
352
|
-
kameleoon_client.add_data(visitor_code, PageView("www.test.com", "test-title"))
|
|
353
|
-
kameleoon_client.add_data(visitor_code, Conversion(1, 100.0))
|
|
354
|
+
kameleoon_client.add_data(visitor_code, PageView("www.test.com", "test-title"), track=True)
|
|
355
|
+
kameleoon_client.add_data(visitor_code, Conversion(1, 100.0), track=False)
|
|
354
356
|
"""
|
|
355
|
-
KameleoonLogger.info(
|
|
357
|
+
KameleoonLogger.info(
|
|
358
|
+
"CALL: KameleoonClient.add_data(visitor_code: %s, args: %s, track: %s)", visitor_code, args, track
|
|
359
|
+
)
|
|
356
360
|
validate_visitor_code(visitor_code)
|
|
357
|
-
self._visitor_manager.add_data(visitor_code, *args)
|
|
358
|
-
KameleoonLogger.info(
|
|
361
|
+
self._visitor_manager.add_data(visitor_code, *args, track=track)
|
|
362
|
+
KameleoonLogger.info(
|
|
363
|
+
"RETURN: KameleoonClient.add_data(visitor_code: %s, args: %s, track: %s)", visitor_code, args, track
|
|
364
|
+
)
|
|
359
365
|
|
|
360
366
|
def track_conversion(
|
|
361
367
|
self,
|
|
@@ -481,7 +487,7 @@ class KameleoonClient:
|
|
|
481
487
|
)
|
|
482
488
|
|
|
483
489
|
def is_feature_active(
|
|
484
|
-
self, visitor_code: str, feature_key: str, is_unique_identifier: Optional[bool] = None, track=True
|
|
490
|
+
self, visitor_code: str, feature_key: str, is_unique_identifier: Optional[bool] = None, track: bool = True
|
|
485
491
|
) -> bool:
|
|
486
492
|
"""
|
|
487
493
|
Check if feature is active for a given visitor code
|
|
@@ -561,7 +567,7 @@ class KameleoonClient:
|
|
|
561
567
|
)
|
|
562
568
|
return feature_active
|
|
563
569
|
|
|
564
|
-
def get_variation(self, visitor_code: str, feature_key: str, track=True) -> Variation:
|
|
570
|
+
def get_variation(self, visitor_code: str, feature_key: str, track: bool = True) -> Variation:
|
|
565
571
|
"""
|
|
566
572
|
Retrieves the variation assigned to the given visitor for a specific feature flag.
|
|
567
573
|
|
|
@@ -605,7 +611,7 @@ class KameleoonClient:
|
|
|
605
611
|
)
|
|
606
612
|
return external_variation
|
|
607
613
|
|
|
608
|
-
def get_variations(self, visitor_code: str, only_active=False, track=True) -> Dict[str, Variation]:
|
|
614
|
+
def get_variations(self, visitor_code: str, only_active=False, track: bool = True) -> Dict[str, Variation]:
|
|
609
615
|
"""
|
|
610
616
|
Forms a dictionary of variations assigned to a given visitor across all feature flags.
|
|
611
617
|
This method iterates over all available feature flags and returns the assigned variation for each flag
|
|
@@ -757,6 +763,11 @@ class KameleoonClient:
|
|
|
757
763
|
save,
|
|
758
764
|
bucketing_cd_index,
|
|
759
765
|
)
|
|
766
|
+
consent, blocking_behaviour = self.__get_consent_and_blocking_behaviour(visitor)
|
|
767
|
+
if consent == LegalConsent.NOT_GIVEN and blocking_behaviour == ConsentBlockingBehaviour.COMPLETELY_BLOCKED:
|
|
768
|
+
raise FeatureEnvironmentDisabled(
|
|
769
|
+
"Evaluation for a holdout is blocked because visitor's consent was not provided."
|
|
770
|
+
)
|
|
760
771
|
is_not_in_holdout = True
|
|
761
772
|
code_for_hash = self.__get_code_for_hash(visitor, visitor_code, bucketing_cd_index)
|
|
762
773
|
variation_hash = Hasher.obtain(code_for_hash, holdout.id_)
|
|
@@ -1610,7 +1621,7 @@ class KameleoonClient:
|
|
|
1610
1621
|
)
|
|
1611
1622
|
return (feature_flag, variation_key)
|
|
1612
1623
|
|
|
1613
|
-
def __save_variation(self, visitor_code: str, eval_exp: Optional[EvaluatedExperiment], track=True) -> None:
|
|
1624
|
+
def __save_variation(self, visitor_code: str, eval_exp: Optional[EvaluatedExperiment], track: bool = True) -> None:
|
|
1614
1625
|
if (eval_exp is None) or (eval_exp.experiment.id_ is None) or (eval_exp.var_by_exp.variation_id is None):
|
|
1615
1626
|
return
|
|
1616
1627
|
KameleoonLogger.debug(
|
|
@@ -1695,11 +1706,7 @@ class KameleoonClient:
|
|
|
1695
1706
|
feature_flag,
|
|
1696
1707
|
)
|
|
1697
1708
|
visitor = self._visitor_manager.get_visitor(visitor_code)
|
|
1698
|
-
|
|
1699
|
-
if datafile.settings.is_consent_required:
|
|
1700
|
-
consent = visitor.legal_consent if visitor else LegalConsent.UNKNOWN
|
|
1701
|
-
else:
|
|
1702
|
-
consent = LegalConsent.GIVEN
|
|
1709
|
+
consent, blocking_behaviour = self.__get_consent_and_blocking_behaviour(visitor)
|
|
1703
1710
|
code_for_hash = self.__get_code_for_hash(visitor, visitor_code, feature_flag.bucketing_custom_data_index)
|
|
1704
1711
|
eval_exp = None
|
|
1705
1712
|
for rule in feature_flag.rules:
|
|
@@ -1722,7 +1729,6 @@ class KameleoonClient:
|
|
|
1722
1729
|
if hash_rule <= rule.exposition:
|
|
1723
1730
|
# Checking if the evaluation is blocked due to the consent policy
|
|
1724
1731
|
if (consent == LegalConsent.NOT_GIVEN) and rule.is_experimentation:
|
|
1725
|
-
blocking_behaviour = datafile.settings.blocking_behaviour_if_consent_not_given
|
|
1726
1732
|
if blocking_behaviour == ConsentBlockingBehaviour.PARTIALLY_BLOCKED:
|
|
1727
1733
|
break
|
|
1728
1734
|
raise FeatureEnvironmentDisabled(
|
|
@@ -1757,6 +1763,19 @@ class KameleoonClient:
|
|
|
1757
1763
|
)
|
|
1758
1764
|
return eval_exp
|
|
1759
1765
|
|
|
1766
|
+
def __get_consent_and_blocking_behaviour(
|
|
1767
|
+
self,
|
|
1768
|
+
visitor: Optional[Visitor],
|
|
1769
|
+
) -> Tuple[LegalConsent, ConsentBlockingBehaviour]:
|
|
1770
|
+
datafile = self._data_manager.data_file
|
|
1771
|
+
if datafile.settings.is_consent_required:
|
|
1772
|
+
consent = visitor.legal_consent if visitor else LegalConsent.UNKNOWN
|
|
1773
|
+
else:
|
|
1774
|
+
consent = LegalConsent.GIVEN
|
|
1775
|
+
behaviour = datafile.settings.blocking_behaviour_if_consent_not_given
|
|
1776
|
+
|
|
1777
|
+
return consent, behaviour
|
|
1778
|
+
|
|
1760
1779
|
@staticmethod
|
|
1761
1780
|
def __calculate_variation_key(eval_exp: Optional[EvaluatedExperiment], default_value: str) -> str:
|
|
1762
1781
|
KameleoonLogger.debug(
|
|
@@ -15,8 +15,8 @@ DEFAULT_REFRESH_INTERVAL_MINUTES = 60
|
|
|
15
15
|
DEFAULT_SESSION_DURATION_MINUTES = 30
|
|
16
16
|
DEFAULT_DEFAULT_TIMEOUT_MILLISECONDS = 10_000
|
|
17
17
|
DEFAULT_TRACKING_INTERVAL_MILLISECONDS = 1000
|
|
18
|
-
MIN_TRACKING_INTERVAL_MILLISECONDS =
|
|
19
|
-
MAX_TRACKING_INTERVAL_MILLISECONDS =
|
|
18
|
+
MIN_TRACKING_INTERVAL_MILLISECONDS = 1_000
|
|
19
|
+
MAX_TRACKING_INTERVAL_MILLISECONDS = 5_000
|
|
20
20
|
DEFAULT_CONFIGURATION_PATH = "/etc/kameleoon/client-python.yaml"
|
|
21
21
|
|
|
22
22
|
|
|
@@ -50,15 +50,15 @@ class RemoteVisitorData:
|
|
|
50
50
|
self.__visitor_code: Optional[str] = None
|
|
51
51
|
current_visit = json.get("currentVisit")
|
|
52
52
|
if current_visit is not None:
|
|
53
|
-
self.__parse_visit(current_visit,
|
|
53
|
+
self.__parse_visit(current_visit, 0)
|
|
54
54
|
previous_visits = json.get("previousVisits")
|
|
55
55
|
if previous_visits:
|
|
56
56
|
prev_visits = []
|
|
57
|
-
for visit in previous_visits:
|
|
57
|
+
for i, visit in enumerate(previous_visits):
|
|
58
58
|
time_started = visit.get("timeStarted", 0)
|
|
59
59
|
time_last_event = visit.get("timeLastEvent", time_started)
|
|
60
60
|
prev_visits.append(VisitorVisits.Visit(time_started, time_last_event))
|
|
61
|
-
self.__parse_visit(visit,
|
|
61
|
+
self.__parse_visit(visit, i + 1)
|
|
62
62
|
if len(prev_visits) > 0:
|
|
63
63
|
self.__visitor_visits = VisitorVisits(prev_visits, self.__visit_number)
|
|
64
64
|
self.__kcs_heat = self.__parse_kcs_heat(json.get("kcs"))
|
|
@@ -123,7 +123,7 @@ class RemoteVisitorData:
|
|
|
123
123
|
"""Returns the `visitorCode` from the most recent visit"""
|
|
124
124
|
return self.__visitor_code
|
|
125
125
|
|
|
126
|
-
def __parse_visit(self, json_visit: Dict[str, Any],
|
|
126
|
+
def __parse_visit(self, json_visit: Dict[str, Any], visit_offset: int) -> None:
|
|
127
127
|
if (self.__visitor_code is None) and isinstance(visitor_code := json_visit.get("visitorCode"), str):
|
|
128
128
|
self.__visitor_code = visitor_code
|
|
129
129
|
custom_data_events = json_visit.get("customDataEvents")
|
|
@@ -143,7 +143,7 @@ class RemoteVisitorData:
|
|
|
143
143
|
self.__parse_geolocation(geolocation_events[-1])
|
|
144
144
|
static_data_event = json_visit.get("staticDataEvent")
|
|
145
145
|
if static_data_event:
|
|
146
|
-
self.__parse_static_data(static_data_event,
|
|
146
|
+
self.__parse_static_data(static_data_event, visit_offset)
|
|
147
147
|
personalization_events = json_visit.get("personalizationEvents")
|
|
148
148
|
if personalization_events:
|
|
149
149
|
self.__parse_personalizations(personalization_events)
|
|
@@ -209,15 +209,13 @@ class RemoteVisitorData:
|
|
|
209
209
|
if country is not None:
|
|
210
210
|
self.__geolocation = Geolocation(country, data.get("region"), data.get("city"))
|
|
211
211
|
|
|
212
|
-
def __parse_static_data(self, static_data_event: Dict[str, Any],
|
|
212
|
+
def __parse_static_data(self, static_data_event: Dict[str, Any], visit_offset: int) -> None:
|
|
213
213
|
if self.__device and self.__browser and self.__operating_system:
|
|
214
214
|
return
|
|
215
215
|
data = static_data_event.get("data")
|
|
216
216
|
if data is not None:
|
|
217
|
-
if self.__visit_number == 0:
|
|
218
|
-
self.__visit_number =
|
|
219
|
-
if is_prev_visit and (self.__visit_number > 0):
|
|
220
|
-
self.__visit_number += 1
|
|
217
|
+
if (self.__visit_number == 0) and (remote_visit_number := data.get("visitNumber")):
|
|
218
|
+
self.__visit_number = remote_visit_number + visit_offset
|
|
221
219
|
if self.__filter.device and (self.__device is None):
|
|
222
220
|
device_type = enum_from_name_literal(data.get("deviceType"), DeviceType, None)
|
|
223
221
|
if device_type is not None:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Kameleoon SDK version"""
|
|
2
|
+
|
|
3
|
+
version_info = (3, 18, 0)
|
|
4
|
+
__version__ = ".".join(str(v) for v in version_info) # uses in scripts
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# pylint: disable=R0903
|
|
8
|
+
class SdkVersion:
|
|
9
|
+
"""SdkVersion is a helper class for get name and version of sdk"""
|
|
10
|
+
|
|
11
|
+
NAME = "PYTHON"
|
|
12
|
+
VERSION = __version__
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Browser condition"""
|
|
2
|
+
|
|
2
3
|
from typing import Any, Dict, Union
|
|
3
4
|
from kameleoon.data import Browser, BrowserType
|
|
5
|
+
from kameleoon.helpers.sem_version import SemVersion
|
|
4
6
|
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
5
|
-
from kameleoon.sdk_version import SdkVersion
|
|
6
7
|
from kameleoon.targeting.conditions.constants import TargetingOperator
|
|
7
8
|
from kameleoon.targeting.conditions.targeting_condition import TargetingCondition
|
|
8
9
|
|
|
@@ -40,7 +41,8 @@ class BrowserCondition(TargetingCondition):
|
|
|
40
41
|
return True
|
|
41
42
|
|
|
42
43
|
# If browser types are equal and browser version is defined in condition, then need to compare versions
|
|
43
|
-
|
|
44
|
+
version = SemVersion.from_string(str(self.__version))
|
|
45
|
+
version_number = version.to_float() if version else None
|
|
44
46
|
if version_number is None:
|
|
45
47
|
return False
|
|
46
48
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Sdk language condition"""
|
|
2
|
+
from typing import Any, Dict, Union
|
|
3
|
+
|
|
4
|
+
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
5
|
+
from kameleoon.targeting.conditions.version_condition import VersionCondition
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SdkLanguageCondition(VersionCondition):
|
|
9
|
+
"""SdkLanguage uses in case if you need to target by sdk type and version"""
|
|
10
|
+
|
|
11
|
+
class SdkInfo:
|
|
12
|
+
"""SdkInfo is a helper class to pass sdk name and version as parameters"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, sdk_language: str, version: str) -> None:
|
|
15
|
+
self.__sdk_language = sdk_language
|
|
16
|
+
self.__version = version
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def sdk_language(self):
|
|
20
|
+
"""Return sdk language (type)"""
|
|
21
|
+
return self.__sdk_language
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def version(self):
|
|
25
|
+
"""Return sdk version"""
|
|
26
|
+
return self.__version
|
|
27
|
+
|
|
28
|
+
def __init__(self, json_condition: Dict[str, Union[str, int, Any]]):
|
|
29
|
+
super().__init__(json_condition)
|
|
30
|
+
try:
|
|
31
|
+
self.__sdk_language = json_condition.get("sdkLanguage", "")
|
|
32
|
+
except KeyError as ex:
|
|
33
|
+
KameleoonLogger.error("%s has wrong JSON structure: %s", self.__class__, ex)
|
|
34
|
+
|
|
35
|
+
def check(self, data: Any) -> bool:
|
|
36
|
+
return isinstance(data, SdkLanguageCondition.SdkInfo) and \
|
|
37
|
+
self.__sdk_language == data.sdk_language and \
|
|
38
|
+
(self._condition_version is None or self.check_targeting(data.version))
|