kameleoon-client-python 3.18.0__tar.gz → 3.19.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.18.0 → kameleoon_client_python-3.19.0}/PKG-INFO +16 -16
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/data_file.py +42 -15
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/variation.py +2 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/visitor_manager.py +16 -1
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/kameleoon_client.py +31 -43
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/data/data_manager.py +7 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/tracking/tracking_builder.py +1 -1
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/access_token_source.py +9 -1
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/net_provider.py +8 -2
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/automation_service.py +1 -1
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/automation_service_impl.py +7 -8
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/url_provider.py +10 -6
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/sdk_version.py +1 -1
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/unknown_condition.py +3 -0
- kameleoon_client_python-3.19.0/kameleoon/types/data_file.py +38 -0
- kameleoon_client_python-3.19.0/kameleoon/types/feature_flag.py +69 -0
- kameleoon_client_python-3.19.0/kameleoon/types/rule.py +40 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/types/variable.py +7 -3
- kameleoon_client_python-3.19.0/kameleoon/types/variation.py +89 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon_client_python.egg-info/PKG-INFO +16 -16
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon_client_python.egg-info/SOURCES.txt +3 -0
- kameleoon_client_python-3.18.0/kameleoon/types/variation.py +0 -46
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/MANIFEST.in +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/README.md +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/client_readiness/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/client_readiness/async_readiness.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/client_readiness/threading_readiness.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/consent_blocking_behaviour.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/custom_data_info.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/experiment.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/feature_flag.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/me_group.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/rule.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/rule_type.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/settings.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/variable.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/configuration/variation_by_exposition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/application_version.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/browser.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/cbscores.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/conversion.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/cookie.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/custom_data.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/data.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/device.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/geolocation.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/kcs_heat.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/assigned_variation.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/forced_experiment_variation.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/forced_feature_variation.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/forced_variation.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/legal_consent.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/page_view_visit.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/visitor.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/manager/visitor_slot.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/mapping_identifier.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/operating_system.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/page_view.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/personalization.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/targeted_segment.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/unique_identifier.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/user_agent.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/data/visitor_visits.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/defaults.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/exceptions.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/domain.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/functions.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/hasher.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/logger.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/multi_threading.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/nonce.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/repeat_timer.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/scheduler.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/sem_version.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/string_utils.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/helpers/visitor_code.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/hybrid/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/hybrid/hybrid_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/hybrid/hybrid_manager_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/kameleoon_client_config.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/kameleoon_client_factory.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/logging/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/logging/kameleoon_logger.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/logging/log_level.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/logging/logger.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/asyncexec/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/asyncexec/async_executor.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/data/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/evaluation/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/evaluation/evaluated_experiment.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/remote_data/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/remote_data/remote_data_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/remote_data/remote_visitor_data.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/tracking/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/tracking/tracking_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/tracking/visitor_tracking_registry.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/warehouse/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/managers/warehouse/warehouse_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/middleware.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/access_token_source_factory.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/activity_event.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/cookie/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/cookie/cookie_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/net_provider_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/network_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/network_manager_factory.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/network_manager_factory_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/network_manager_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/query_builder.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/query_encodable.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/sendable.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/service_initialize_context.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/service_initialize_context_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/configuration_service.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/configuration_service_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/data_service.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/data_service_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/service.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/services/service_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/uri_helper.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/real_time/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/real_time/real_time_configuration_service.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/real_time/real_time_event.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/storage/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/storage/cache.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/storage/cache_factory.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/storage/cache_factory_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/storage/cache_impl.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/browser_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/constants.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/conversion_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/cookie_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/custom_datum.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/device_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/exclusive_experiment_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/geolocation_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/kcs_heat_range_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/number_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/operating_system_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/page_title_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/page_url_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/page_view_number_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/previous_page_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/sdk_language_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/segment_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/string_value_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/target_experiment_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/target_feature_flag_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/target_personalization_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/targeting_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/version_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/visit_number_today_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/visit_number_total_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/visitor_code_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/conditions/visitor_new_return_condition.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/models.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/targeting_manager.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/tree_builder.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/targeting/tree_condition_factory.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/types/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/types/remote_visitor_data_filter.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon_client_python.egg-info/dependency_links.txt +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon_client_python.egg-info/requires.txt +15 -15
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon_client_python.egg-info/top_level.txt +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/setup.cfg +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/setup.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/admin.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/apps.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/migrations/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/models.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/tests.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/kameleoon_app/views.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/manage.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/proj/__init__.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/proj/asgi.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/proj/settings.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/proj/urls.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/tests/integration/proj/proj/wsgi.py +0 -0
- {kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.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.19.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:
|
|
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"
|
|
27
|
-
Requires-Dist: aioresponses==0.7.*; extra == "test"
|
|
28
|
-
Requires-Dist: twine==3.4.1; extra == "test"
|
|
29
|
-
Requires-Dist: pytest-django==4.4.0; extra == "test"
|
|
30
|
-
Requires-Dist: Django==3.2.4; extra == "test"
|
|
31
|
-
Requires-Dist: pytest-cov==2.12.1; extra == "test"
|
|
32
|
-
Requires-Dist: types-python-dateutil==2.8.2; extra == "test"
|
|
33
|
-
Requires-Dist: pylint==2.12.*; extra == "test"
|
|
34
|
-
Requires-Dist: aiohttp<4.0.0,>=3.8.0; extra == "test"
|
|
23
|
+
Requires-Dist: wheel==0.36.2; extra == "test"
|
|
35
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
|
+
Requires-Dist: types-requests==2.25.0; extra == "test"
|
|
36
28
|
Requires-Dist: pytest-asyncio==0.21.*; extra == "test"
|
|
37
29
|
Requires-Dist: sseclient-py<1.9.0,>=1.7.0; extra == "test"
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist: types-
|
|
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"
|
|
40
33
|
Requires-Dist: pyyaml<6.1.0,>=5.4.0; extra == "test"
|
|
34
|
+
Requires-Dist: pytest-django==4.4.0; extra == "test"
|
|
41
35
|
Requires-Dist: pytest-ordering==0.6; extra == "test"
|
|
42
|
-
Requires-Dist:
|
|
36
|
+
Requires-Dist: Django==3.2.4; extra == "test"
|
|
37
|
+
Requires-Dist: types-PyYAML==5.4.3; extra == "test"
|
|
38
|
+
Requires-Dist: flake8==4.0.1; extra == "test"
|
|
39
|
+
Requires-Dist: pytest-pythonpath==0.7.3; extra == "test"
|
|
40
|
+
Requires-Dist: mypy==0.991; extra == "test"
|
|
43
41
|
Requires-Dist: requests<3.0.0,>=2.25; extra == "test"
|
|
42
|
+
Requires-Dist: twine==3.4.1; extra == "test"
|
|
43
|
+
Requires-Dist: aioresponses==0.7.*; extra == "test"
|
|
44
44
|
Dynamic: author
|
|
45
45
|
Dynamic: author-email
|
|
46
46
|
Dynamic: classifier
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Kameleoon Configuration"""
|
|
2
2
|
|
|
3
3
|
from typing import Any, Dict, Iterable, List, Optional, Set
|
|
4
|
+
|
|
4
5
|
from kameleoon.configuration import Variable
|
|
5
6
|
from kameleoon.configuration.custom_data_info import CustomDataInfo
|
|
6
7
|
from kameleoon.configuration.experiment import Experiment
|
|
@@ -20,7 +21,7 @@ class DataFile:
|
|
|
20
21
|
@staticmethod
|
|
21
22
|
def default(environment: Optional[str]) -> "DataFile":
|
|
22
23
|
"""Creates new instance of `DataFile` initialized with default values"""
|
|
23
|
-
data_file = DataFile(environment, None, Settings(), {}, {}, CustomDataInfo(None))
|
|
24
|
+
data_file = DataFile(environment, None, Settings(), {}, {}, CustomDataInfo(None), None, 0)
|
|
24
25
|
return data_file
|
|
25
26
|
|
|
26
27
|
@staticmethod
|
|
@@ -33,23 +34,29 @@ class DataFile:
|
|
|
33
34
|
custom_data_info = CustomDataInfo(configuration.get("customData"))
|
|
34
35
|
feature_flags = DataFile.__parse_feature_flags(configuration, segments, custom_data_info)
|
|
35
36
|
holdout = Experiment.from_json(configuration["holdout"]) if "holdout" in configuration else None
|
|
36
|
-
|
|
37
|
+
date_modified = int(configuration.get("dateModified", 0))
|
|
38
|
+
data_file = DataFile(
|
|
39
|
+
environment,
|
|
40
|
+
last_modified,
|
|
41
|
+
settings,
|
|
42
|
+
segments,
|
|
43
|
+
feature_flags,
|
|
44
|
+
custom_data_info,
|
|
45
|
+
holdout,
|
|
46
|
+
date_modified,
|
|
47
|
+
)
|
|
37
48
|
return data_file
|
|
38
49
|
|
|
39
50
|
@staticmethod
|
|
40
51
|
def __parse_segments(configuration: Dict[str, Any]) -> Dict[int, Segment]:
|
|
41
|
-
return {
|
|
42
|
-
(seg := Segment.from_json(jobj)).id_: seg
|
|
43
|
-
for jobj in configuration.get("segments") or []
|
|
44
|
-
}
|
|
52
|
+
return {(seg := Segment.from_json(jobj)).id_: seg for jobj in configuration.get("segments") or []}
|
|
45
53
|
|
|
46
54
|
@staticmethod
|
|
47
55
|
def __parse_feature_flags(
|
|
48
56
|
configuration: Dict[str, Any], segments: Dict[int, Segment], cdi: CustomDataInfo
|
|
49
57
|
) -> Dict[str, FeatureFlag]:
|
|
50
58
|
return {
|
|
51
|
-
(ff := FeatureFlag(jobj, segments, cdi)).feature_key: ff
|
|
52
|
-
for jobj in configuration.get("featureFlags") or []
|
|
59
|
+
(ff := FeatureFlag(jobj, segments, cdi)).feature_key: ff for jobj in configuration.get("featureFlags") or []
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
# pylint: disable=R0913
|
|
@@ -61,15 +68,22 @@ class DataFile:
|
|
|
61
68
|
segments: Dict[int, Segment],
|
|
62
69
|
feature_flags: Dict[str, FeatureFlag],
|
|
63
70
|
custom_data_info: CustomDataInfo,
|
|
64
|
-
holdout: Optional[Experiment]
|
|
71
|
+
holdout: Optional[Experiment],
|
|
72
|
+
date_modified: int,
|
|
65
73
|
) -> None:
|
|
66
74
|
KameleoonLogger.debug(
|
|
67
75
|
"CALL: DataFile(environment: %s, last_modified: %s, settings: %s, segments, feature_flags,"
|
|
68
|
-
" custom_data_info: %s, holdout: %s)",
|
|
69
|
-
environment,
|
|
76
|
+
" custom_data_info: %s, holdout: %s, date_modified: %s)",
|
|
77
|
+
environment,
|
|
78
|
+
last_modified,
|
|
79
|
+
settings,
|
|
80
|
+
custom_data_info,
|
|
81
|
+
holdout,
|
|
82
|
+
date_modified,
|
|
70
83
|
)
|
|
71
84
|
self.__environment = environment # pylint: disable=W0238
|
|
72
85
|
self.__last_modified = last_modified
|
|
86
|
+
self.__date_modified = date_modified
|
|
73
87
|
self.__settings = settings
|
|
74
88
|
self.__segments = segments
|
|
75
89
|
self.__audience_tracking_segments = [seg for seg in segments.values() if seg.audience_tracking]
|
|
@@ -90,8 +104,13 @@ class DataFile:
|
|
|
90
104
|
self.__holdout = holdout
|
|
91
105
|
KameleoonLogger.debug(
|
|
92
106
|
"RETURN: DataFile(environment: %s, last_modified: %s, settings: %s, segments, feature_flags,"
|
|
93
|
-
" custom_data_info: %s, holdout: %s)",
|
|
94
|
-
environment,
|
|
107
|
+
" custom_data_info: %s, holdout: %s, date_modified: %s)",
|
|
108
|
+
environment,
|
|
109
|
+
last_modified,
|
|
110
|
+
settings,
|
|
111
|
+
custom_data_info,
|
|
112
|
+
holdout,
|
|
113
|
+
date_modified,
|
|
95
114
|
)
|
|
96
115
|
|
|
97
116
|
@property
|
|
@@ -99,6 +118,11 @@ class DataFile:
|
|
|
99
118
|
"""Returns last modified string"""
|
|
100
119
|
return self.__last_modified
|
|
101
120
|
|
|
121
|
+
@property
|
|
122
|
+
def date_modified(self) -> int:
|
|
123
|
+
"""Returns the last data-file update timestamp from the configuration."""
|
|
124
|
+
return self.__date_modified
|
|
125
|
+
|
|
102
126
|
@property
|
|
103
127
|
def settings(self) -> Settings:
|
|
104
128
|
"""Returns settings"""
|
|
@@ -152,10 +176,12 @@ class DataFile:
|
|
|
152
176
|
feature_flag = self.__feature_flags.get(feature_key)
|
|
153
177
|
if feature_flag is None:
|
|
154
178
|
raise FeatureNotFound(feature_key)
|
|
179
|
+
return feature_flag
|
|
180
|
+
|
|
181
|
+
def _ensure_environment_enabled(self, feature_flag: FeatureFlag):
|
|
155
182
|
if not feature_flag.environment_enabled:
|
|
156
183
|
env = "default" if self.__environment is None else f"'{self.__environment}'"
|
|
157
|
-
raise FeatureEnvironmentDisabled(f"Feature '{feature_key}' is disabled for {env} environment")
|
|
158
|
-
return feature_flag
|
|
184
|
+
raise FeatureEnvironmentDisabled(f"Feature '{feature_flag.feature_key}' is disabled for {env} environment")
|
|
159
185
|
|
|
160
186
|
@property
|
|
161
187
|
def custom_data_info(self) -> CustomDataInfo:
|
|
@@ -211,6 +237,7 @@ class DataFile:
|
|
|
211
237
|
"DataFile{"
|
|
212
238
|
f"environment:'{self.__environment}',"
|
|
213
239
|
f"last_modified:'{self.__last_modified}',"
|
|
240
|
+
f"date_modified:{self.__date_modified},"
|
|
214
241
|
f"feature_flags:{len(self.__feature_flags)},"
|
|
215
242
|
f"settings:{self.__settings}"
|
|
216
243
|
"}"
|
|
@@ -23,6 +23,7 @@ class Variation:
|
|
|
23
23
|
|
|
24
24
|
def __init__(self, dict_json: Dict[str, Any]):
|
|
25
25
|
self.key: str = dict_json.get("key", "")
|
|
26
|
+
self.name: str = dict_json.get("name", "")
|
|
26
27
|
self.variables: List[Variable] = Variable.from_array(
|
|
27
28
|
dict_json.get("variables", [])
|
|
28
29
|
)
|
|
@@ -33,4 +34,5 @@ class Variation:
|
|
|
33
34
|
|
|
34
35
|
def __str__(self):
|
|
35
36
|
return (f"Variation{{key:'{self.key}',"
|
|
37
|
+
f"name:'{self.name}',"
|
|
36
38
|
f"variables:{StringUtils.object_to_string(self.variables)}}}")
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
import collections
|
|
4
4
|
import time
|
|
5
5
|
from typing import Any, Dict, Iterator, List, Optional
|
|
6
|
+
|
|
6
7
|
from kameleoon.configuration.custom_data_info import CustomDataInfo
|
|
7
8
|
from kameleoon.data import Conversion, CustomData
|
|
8
|
-
from kameleoon.data.mapping_identifier import MappingIdentifier
|
|
9
9
|
from kameleoon.data.manager.visitor import Visitor
|
|
10
10
|
from kameleoon.data.manager.visitor_slot import VisitorSlot
|
|
11
|
+
from kameleoon.data.mapping_identifier import MappingIdentifier
|
|
11
12
|
from kameleoon.helpers.scheduler import Scheduler
|
|
12
13
|
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
13
14
|
from kameleoon.managers.data.data_manager import DataManager
|
|
@@ -63,6 +64,20 @@ class VisitorManager:
|
|
|
63
64
|
slot.lock.release()
|
|
64
65
|
KameleoonLogger.debug("RETURN: VisitorManager.get_or_create_visitor(visitor_code: %s)", visitor_code)
|
|
65
66
|
|
|
67
|
+
def peek_visitor(self, visitor_code: str) -> Optional[Visitor]:
|
|
68
|
+
"""Retrieves a visitor by their code if it exists, otherwise returns `None`."""
|
|
69
|
+
KameleoonLogger.debug(f"CALL: VisitorManager.peekVisitor(visitor_code: {visitor_code})")
|
|
70
|
+
if (slot := self.__try_acquire_slot(visitor_code)) is None:
|
|
71
|
+
visitor = None
|
|
72
|
+
else:
|
|
73
|
+
try:
|
|
74
|
+
visitor = slot.visitor
|
|
75
|
+
finally:
|
|
76
|
+
slot.lock.release()
|
|
77
|
+
KameleoonLogger.debug(
|
|
78
|
+
f"RETURN: VisitorManager.peekVisitor(visitor_code: {visitor_code}) -> "f"(visitor: {visitor})")
|
|
79
|
+
return visitor
|
|
80
|
+
|
|
66
81
|
def add_data(self, visitor_code: str, *args, track: bool = True) -> Visitor:
|
|
67
82
|
"""
|
|
68
83
|
Adds data to a visitor.
|
{kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/kameleoon_client.py
RENAMED
|
@@ -3,16 +3,14 @@
|
|
|
3
3
|
from http.cookies import Morsel
|
|
4
4
|
from typing import cast, Callable, Coroutine, Optional, Tuple, Union, Any, List, Dict, Iterable
|
|
5
5
|
|
|
6
|
+
from kameleoon import configuration
|
|
6
7
|
from kameleoon.client_readiness.async_readiness import AsyncClientReadiness
|
|
7
8
|
from kameleoon.client_readiness.threading_readiness import ThreadingClientReadiness
|
|
8
|
-
|
|
9
|
-
from kameleoon import configuration
|
|
10
9
|
from kameleoon.configuration.consent_blocking_behaviour import ConsentBlockingBehaviour
|
|
11
10
|
from kameleoon.configuration.data_file import DataFile
|
|
12
11
|
from kameleoon.configuration.feature_flag import FeatureFlag
|
|
13
12
|
from kameleoon.configuration.rule import Rule
|
|
14
13
|
from kameleoon.configuration.rule_type import RuleType
|
|
15
|
-
|
|
16
14
|
from kameleoon.data import Conversion, CustomData, Data, UniqueIdentifier
|
|
17
15
|
from kameleoon.data.manager.assigned_variation import AssignedVariation
|
|
18
16
|
from kameleoon.data.manager.forced_experiment_variation import ForcedExperimentVariation
|
|
@@ -20,7 +18,6 @@ from kameleoon.data.manager.legal_consent import LegalConsent
|
|
|
20
18
|
from kameleoon.data.manager.visitor import Visitor
|
|
21
19
|
from kameleoon.data.manager.visitor_manager import VisitorManager
|
|
22
20
|
from kameleoon.data.targeted_segment import TargetedSegment
|
|
23
|
-
|
|
24
21
|
from kameleoon.exceptions import (
|
|
25
22
|
FeatureVariationNotFound,
|
|
26
23
|
FeatureExperimentNotFound,
|
|
@@ -28,37 +25,28 @@ from kameleoon.exceptions import (
|
|
|
28
25
|
FeatureEnvironmentDisabled,
|
|
29
26
|
SiteCodeIsEmpty,
|
|
30
27
|
)
|
|
31
|
-
|
|
32
28
|
from kameleoon.helpers.hasher import Hasher
|
|
33
29
|
from kameleoon.helpers.visitor_code import validate_visitor_code
|
|
34
|
-
|
|
35
30
|
from kameleoon.hybrid.hybrid_manager_impl import HybridManagerImpl
|
|
36
|
-
|
|
37
31
|
from kameleoon.kameleoon_client_config import KameleoonClientConfig
|
|
38
32
|
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
39
33
|
from kameleoon.logging.logger import DefaultLogger
|
|
40
|
-
|
|
41
34
|
from kameleoon.managers.asyncexec.async_executor import AsyncExecutor
|
|
42
35
|
from kameleoon.managers.data.data_manager import DataManager
|
|
43
36
|
from kameleoon.managers.evaluation.evaluated_experiment import EvaluatedExperiment
|
|
44
37
|
from kameleoon.managers.remote_data.remote_data_manager import RemoteDataManager
|
|
45
38
|
from kameleoon.managers.tracking.tracking_manager import TrackingManager
|
|
46
39
|
from kameleoon.managers.warehouse.warehouse_manager import WarehouseManager
|
|
47
|
-
|
|
48
40
|
from kameleoon.network.access_token_source_factory import AccessTokenSourceFactory
|
|
41
|
+
from kameleoon.network.cookie.cookie_manager import CookieManager
|
|
49
42
|
from kameleoon.network.net_provider_impl import NetProviderImpl
|
|
50
43
|
from kameleoon.network.network_manager_factory import NetworkManagerFactory
|
|
51
44
|
from kameleoon.network.network_manager_factory_impl import NetworkManagerFactoryImpl
|
|
52
45
|
from kameleoon.network.sendable import Sendable
|
|
53
46
|
from kameleoon.network.services.configuration_service import ConfigurationService, FetchedConfiguration
|
|
54
|
-
from kameleoon.network.cookie.cookie_manager import CookieManager
|
|
55
|
-
|
|
56
47
|
from kameleoon.real_time.real_time_configuration_service import RealTimeConfigurationService
|
|
57
|
-
|
|
58
48
|
from kameleoon.targeting.targeting_manager import TargetingManager
|
|
59
|
-
|
|
60
49
|
from kameleoon.types.remote_visitor_data_filter import RemoteVisitorDataFilter
|
|
61
|
-
from kameleoon.types.variable import Variable
|
|
62
50
|
from kameleoon.types.variation import Variation
|
|
63
51
|
|
|
64
52
|
__all__ = [
|
|
@@ -596,9 +584,7 @@ class KameleoonClient:
|
|
|
596
584
|
validate_visitor_code(visitor_code)
|
|
597
585
|
feature_flag = self._data_manager.data_file.get_feature_flag(feature_key)
|
|
598
586
|
variation_key, eval_exp = self.__get_variation_info(visitor_code, feature_flag, track)
|
|
599
|
-
external_variation = self.__create_external_variation(
|
|
600
|
-
variation_key, feature_flag.get_variation(variation_key), eval_exp
|
|
601
|
-
)
|
|
587
|
+
external_variation = self.__create_external_variation(feature_flag.get_variation(variation_key), eval_exp)
|
|
602
588
|
if track:
|
|
603
589
|
self._tracking_manager.add_visitor_code(visitor_code)
|
|
604
590
|
KameleoonLogger.info(
|
|
@@ -611,6 +597,14 @@ class KameleoonClient:
|
|
|
611
597
|
)
|
|
612
598
|
return external_variation
|
|
613
599
|
|
|
600
|
+
def get_data_file(self):
|
|
601
|
+
"""Retrieves the information about the data file"""
|
|
602
|
+
|
|
603
|
+
KameleoonLogger.info("CALL: KameleoonClient.get_data_file()")
|
|
604
|
+
data_file = self._data_manager.external_datafile
|
|
605
|
+
KameleoonLogger.info("RETURN: KameleoonClient.get_data_file() -> (data_file: %s)", data_file)
|
|
606
|
+
return data_file
|
|
607
|
+
|
|
614
608
|
def get_variations(self, visitor_code: str, only_active=False, track: bool = True) -> Dict[str, Variation]:
|
|
615
609
|
"""
|
|
616
610
|
Forms a dictionary of variations assigned to a given visitor across all feature flags.
|
|
@@ -640,8 +634,6 @@ class KameleoonClient:
|
|
|
640
634
|
validate_visitor_code(visitor_code)
|
|
641
635
|
variations: Dict[str, Variation] = {}
|
|
642
636
|
for feature_flag in self._data_manager.data_file.feature_flags.values():
|
|
643
|
-
if not feature_flag.environment_enabled:
|
|
644
|
-
continue
|
|
645
637
|
try:
|
|
646
638
|
variation_key, eval_exp = self.__get_variation_info(visitor_code, feature_flag, track)
|
|
647
639
|
except FeatureEnvironmentDisabled:
|
|
@@ -649,7 +641,7 @@ class KameleoonClient:
|
|
|
649
641
|
if only_active and (variation_key == configuration.Variation.Type.OFF.value):
|
|
650
642
|
continue
|
|
651
643
|
variations[feature_flag.feature_key] = self.__create_external_variation(
|
|
652
|
-
|
|
644
|
+
feature_flag.get_variation(variation_key), eval_exp
|
|
653
645
|
)
|
|
654
646
|
if track:
|
|
655
647
|
self._tracking_manager.add_visitor_code(visitor_code)
|
|
@@ -698,6 +690,10 @@ class KameleoonClient:
|
|
|
698
690
|
)
|
|
699
691
|
eval_exp = None
|
|
700
692
|
forced_variation = visitor.get_forced_feature_variation(feature_flag.feature_key) if visitor else None
|
|
693
|
+
|
|
694
|
+
if not (forced_variation and forced_variation.simulated):
|
|
695
|
+
self._data_manager.data_file._ensure_environment_enabled(feature_flag)
|
|
696
|
+
|
|
701
697
|
if forced_variation:
|
|
702
698
|
eval_exp = EvaluatedExperiment.from_forced_variation(forced_variation)
|
|
703
699
|
elif self.__is_visitor_not_in_holdout(
|
|
@@ -791,31 +787,20 @@ class KameleoonClient:
|
|
|
791
787
|
|
|
792
788
|
@staticmethod
|
|
793
789
|
def __create_external_variation(
|
|
794
|
-
variation_key: str,
|
|
795
790
|
variation: Optional[configuration.Variation],
|
|
796
791
|
eval_exp: Optional[EvaluatedExperiment],
|
|
797
792
|
) -> Variation:
|
|
798
793
|
KameleoonLogger.debug(
|
|
799
|
-
"CALL: KameleoonClient.__create_external_variation(
|
|
800
|
-
"eval_exp: %s)",
|
|
801
|
-
variation_key,
|
|
794
|
+
"CALL: KameleoonClient.__create_external_variation(variation: %s, eval_exp: %s)",
|
|
802
795
|
variation,
|
|
803
796
|
eval_exp,
|
|
804
797
|
)
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
variation_id = None
|
|
810
|
-
experiment_id = None
|
|
811
|
-
if eval_exp:
|
|
812
|
-
variation_id = eval_exp.var_by_exp.variation_id
|
|
813
|
-
experiment_id = eval_exp.experiment.id_
|
|
814
|
-
ext_variation = Variation(variation_key, variation_id, experiment_id, ext_variables)
|
|
798
|
+
variation_id, experiment_id = (
|
|
799
|
+
(eval_exp.var_by_exp.variation_id, eval_exp.experiment.id_) if eval_exp else (None, None)
|
|
800
|
+
)
|
|
801
|
+
ext_variation = Variation._build_from_internal(variation, variation_id, experiment_id)
|
|
815
802
|
KameleoonLogger.debug(
|
|
816
|
-
"RETURN: KameleoonClient.__create_external_variation(
|
|
817
|
-
"eval_exp: %s) -> (ext_variation: %s)",
|
|
818
|
-
variation_key,
|
|
803
|
+
"RETURN: KameleoonClient.__create_external_variation(variation: %s, eval_exp: %s) -> (ext_variation: %s)",
|
|
819
804
|
variation,
|
|
820
805
|
eval_exp,
|
|
821
806
|
ext_variation,
|
|
@@ -863,6 +848,9 @@ class KameleoonClient:
|
|
|
863
848
|
variation_key,
|
|
864
849
|
)
|
|
865
850
|
feature_flag = self._data_manager.data_file.get_feature_flag(feature_key)
|
|
851
|
+
|
|
852
|
+
self._data_manager.data_file._ensure_environment_enabled(feature_flag)
|
|
853
|
+
|
|
866
854
|
variation = feature_flag.get_variation(variation_key)
|
|
867
855
|
if not variation:
|
|
868
856
|
raise FeatureVariationNotFound(variation_key)
|
|
@@ -1164,14 +1152,18 @@ class KameleoonClient:
|
|
|
1164
1152
|
)
|
|
1165
1153
|
return custom_data
|
|
1166
1154
|
|
|
1155
|
+
# Deprecated methods
|
|
1167
1156
|
def get_feature_list(self) -> List[str]:
|
|
1168
1157
|
"""
|
|
1158
|
+
Deprecated function. Please use `get_data_file` instead.
|
|
1159
|
+
|
|
1169
1160
|
The get_feature_list method uses for obtaining a list of feature flag IDs:
|
|
1170
1161
|
- currently available for the SDK
|
|
1171
1162
|
|
|
1172
1163
|
:return: List of all feature flag IDs
|
|
1173
|
-
:rtype: List[
|
|
1164
|
+
:rtype: List[str]
|
|
1174
1165
|
"""
|
|
1166
|
+
KameleoonLogger.info("Call to deprecated function `get_feature_list`. Please use `get_data_file` instead.")
|
|
1175
1167
|
KameleoonLogger.info("CALL: KameleoonClient.get_feature_list()")
|
|
1176
1168
|
features = list(self._data_manager.data_file.feature_flags)
|
|
1177
1169
|
KameleoonLogger.info("RETURN: KameleoonClient.get_feature_list() -> (features: %s)", features)
|
|
@@ -1200,8 +1192,6 @@ class KameleoonClient:
|
|
|
1200
1192
|
visitor = self._visitor_manager.get_visitor(visitor_code)
|
|
1201
1193
|
|
|
1202
1194
|
def filter_conditions(feature_flag: FeatureFlag) -> bool:
|
|
1203
|
-
if not feature_flag.environment_enabled:
|
|
1204
|
-
return False
|
|
1205
1195
|
try:
|
|
1206
1196
|
eval_exp = self.__evaluate(visitor, visitor_code, feature_flag, False, False)
|
|
1207
1197
|
except FeatureEnvironmentDisabled:
|
|
@@ -1251,8 +1241,6 @@ class KameleoonClient:
|
|
|
1251
1241
|
visitor = self._visitor_manager.get_visitor(visitor_code)
|
|
1252
1242
|
map_active_features: Dict[str, Variation] = {}
|
|
1253
1243
|
for feature_flag in self._data_manager.data_file.feature_flags.values():
|
|
1254
|
-
if not feature_flag.environment_enabled:
|
|
1255
|
-
continue
|
|
1256
1244
|
try:
|
|
1257
1245
|
eval_exp = self.__evaluate(visitor, visitor_code, feature_flag, False, False)
|
|
1258
1246
|
except FeatureEnvironmentDisabled:
|
|
@@ -1261,7 +1249,7 @@ class KameleoonClient:
|
|
|
1261
1249
|
if variation_key == configuration.Variation.Type.OFF.value:
|
|
1262
1250
|
continue
|
|
1263
1251
|
map_active_features[feature_flag.feature_key] = self.__create_external_variation(
|
|
1264
|
-
|
|
1252
|
+
feature_flag.get_variation(variation_key), eval_exp
|
|
1265
1253
|
)
|
|
1266
1254
|
KameleoonLogger.info(
|
|
1267
1255
|
"RETURN: KameleoonClient.get_active_features(visitor_code: %s) -> (active_features: %s)",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from kameleoon.configuration.data_file import DataFile
|
|
4
4
|
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
5
|
+
from kameleoon.types.data_file import DataFile as TypesDataFile
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class DataManager:
|
|
@@ -22,6 +23,11 @@ class DataManager:
|
|
|
22
23
|
"""Sets a new `DataFile` for this instance by updating the container."""
|
|
23
24
|
self.__container = DataManager.Container(value)
|
|
24
25
|
|
|
26
|
+
@property
|
|
27
|
+
def external_datafile(self) -> TypesDataFile:
|
|
28
|
+
"""Returns the external `DataFile` associated with this instance."""
|
|
29
|
+
return self.__container.external_datafile
|
|
30
|
+
|
|
25
31
|
@property
|
|
26
32
|
def is_visitor_code_managed(self) -> bool:
|
|
27
33
|
"""Returns `True` if consent is required, otherwise returns `False`."""
|
|
@@ -34,6 +40,7 @@ class DataManager:
|
|
|
34
40
|
def __init__(self, data_file: DataFile) -> None:
|
|
35
41
|
KameleoonLogger.debug("CALL: DataManager.Container(data_file: %s)", data_file)
|
|
36
42
|
self.data_file = data_file
|
|
43
|
+
self.external_datafile = TypesDataFile._build_from_internal(data_file)
|
|
37
44
|
# Regarding GDPR policy we should set visitorCode if legal consent isn't required or we have at
|
|
38
45
|
# least one Targeted Delivery rule in datafile
|
|
39
46
|
self.is_visitor_code_managed = (
|
|
@@ -61,7 +61,7 @@ class TrackingBuilder:
|
|
|
61
61
|
return
|
|
62
62
|
for visitor_code in self.__visitor_codes:
|
|
63
63
|
if self.__total_size <= self.__request_size_limit:
|
|
64
|
-
visitor = self.__visitor_manager.
|
|
64
|
+
visitor = self.__visitor_manager.peek_visitor(visitor_code)
|
|
65
65
|
is_consent_given = self.__is_consent_given(visitor)
|
|
66
66
|
data = self.__collect_tracking_data(visitor_code, visitor, is_consent_given)
|
|
67
67
|
if len(data) > 0:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Network"""
|
|
2
2
|
import asyncio
|
|
3
|
+
import base64
|
|
3
4
|
import time
|
|
4
5
|
from typing import Optional
|
|
5
6
|
|
|
@@ -25,11 +26,18 @@ class AccessTokenSource:
|
|
|
25
26
|
self._client_secret = client_secret
|
|
26
27
|
self._cached_token: Optional[AccessTokenSource.ExpiringToken] = None
|
|
27
28
|
self._fetching = False
|
|
29
|
+
self._basic_authorization_token = AccessTokenSource.construct_basic_token(client_id, client_secret)
|
|
28
30
|
KameleoonLogger.debug(
|
|
29
31
|
lambda: f"RETURN: AccessTokenSource(network_manager, client_id: '{StringUtils.secret(client_id)}', "
|
|
30
32
|
f"client_secret: '{StringUtils.secret(client_secret)}')"
|
|
31
33
|
)
|
|
32
34
|
|
|
35
|
+
@staticmethod
|
|
36
|
+
def construct_basic_token(client_id: str, client_secret: str) -> str:
|
|
37
|
+
"""Returns the basic token"""
|
|
38
|
+
basic_token_content = f"{client_id}:{client_secret}"
|
|
39
|
+
return "Basic " + base64.b64encode(basic_token_content.encode("utf-8")).decode("utf-8")
|
|
40
|
+
|
|
33
41
|
async def get_token(self, timeout: Optional[float] = None) -> Optional[str]:
|
|
34
42
|
"""Returns the access token. Fetches a new token if the cached one is expired or obsolete."""
|
|
35
43
|
KameleoonLogger.debug("CALL: AccessTokenSource.get_token(timeout: %s)", timeout)
|
|
@@ -73,7 +81,7 @@ class AccessTokenSource:
|
|
|
73
81
|
KameleoonLogger.debug("CALL: AccessTokenSource._fetch_token(timeout: %s)", timeout)
|
|
74
82
|
try:
|
|
75
83
|
service: AutomationService = self._network_manager.get_service(AutomationService)
|
|
76
|
-
response = await service.fetch_access_jwtoken(self.
|
|
84
|
+
response = await service.fetch_access_jwtoken(self._basic_authorization_token, timeout)
|
|
77
85
|
if not response.success:
|
|
78
86
|
KameleoonLogger.error("Failed to fetch access JWT")
|
|
79
87
|
return None
|
{kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/net_provider.py
RENAMED
|
@@ -64,8 +64,14 @@ class Request:
|
|
|
64
64
|
def __str__(self):
|
|
65
65
|
body = "None"
|
|
66
66
|
if self.body is not None:
|
|
67
|
-
body =
|
|
68
|
-
|
|
67
|
+
body = self.body
|
|
68
|
+
|
|
69
|
+
headers = [
|
|
70
|
+
f"{name}:{'***' if name == 'Authorization' else value}"
|
|
71
|
+
for name, value in (self.headers or {}).items()
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
return f"HttpRequest{{Method:'{self.method}',Url:'{self.url}',Headers:{headers},Body:{body}}}"
|
|
69
75
|
|
|
70
76
|
|
|
71
77
|
class NetProvider:
|
|
@@ -7,7 +7,7 @@ from kameleoon.network.net_provider import Response
|
|
|
7
7
|
class AutomationService(Service):
|
|
8
8
|
"""Abstract automation service"""
|
|
9
9
|
def fetch_access_jwtoken(
|
|
10
|
-
self,
|
|
10
|
+
self, basic_authorization_token: str, timeout: Optional[float] = None
|
|
11
11
|
) -> Coroutine[Any, Any, Response]:
|
|
12
12
|
"""Fetches an access JWT token asynchronously."""
|
|
13
13
|
raise NotImplementedError()
|
|
@@ -13,6 +13,7 @@ class AutomationServiceImpl(AutomationService, ServiceImpl):
|
|
|
13
13
|
"""Automation service implementation"""
|
|
14
14
|
_ACCESS_TOKEN_GRANT_TYPE = "client_credentials"
|
|
15
15
|
_H_CONTENT_TYPE_NAME = "Content-Type"
|
|
16
|
+
_H_AUTHORIZATION = "Authorization"
|
|
16
17
|
_H_CONTENT_TYPE_VALUE = "application/x-www-form-urlencoded"
|
|
17
18
|
|
|
18
19
|
def __init__(self, network_manager) -> None:
|
|
@@ -22,27 +23,25 @@ class AutomationServiceImpl(AutomationService, ServiceImpl):
|
|
|
22
23
|
KameleoonLogger.debug("RETURN: AutomationServiceImpl(network_manager)")
|
|
23
24
|
|
|
24
25
|
def fetch_access_jwtoken(
|
|
25
|
-
self,
|
|
26
|
+
self, basic_authorization_token: str, timeout: Optional[float] = None
|
|
26
27
|
) -> Coroutine[Any, Any, Response]:
|
|
27
28
|
KameleoonLogger.debug(lambda: f"CALL: AutomationServiceImpl.fetch_access_jwtoken("
|
|
28
|
-
f"
|
|
29
|
-
f"
|
|
29
|
+
f"basic_authorization_token: '{StringUtils.secret(basic_authorization_token)}', "
|
|
30
|
+
f"timeout: {timeout})")
|
|
30
31
|
if timeout is None:
|
|
31
32
|
timeout = self.network_manager.call_timeout
|
|
32
33
|
url: str = self.network_manager.url_provider.make_access_token_url()
|
|
33
34
|
body = QueryBuilder(
|
|
34
35
|
QueryParam(QueryParams.GRANT_TYPE, self._ACCESS_TOKEN_GRANT_TYPE),
|
|
35
|
-
QueryParam(QueryParams.CLIENT_ID, client_id),
|
|
36
|
-
QueryParam(QueryParams.CLIENT_SECRET, client_secret),
|
|
37
36
|
)
|
|
38
|
-
headers = {self._H_CONTENT_TYPE_NAME: self._H_CONTENT_TYPE_VALUE
|
|
37
|
+
headers = {self._H_CONTENT_TYPE_NAME: self._H_CONTENT_TYPE_VALUE,
|
|
38
|
+
self._H_AUTHORIZATION: basic_authorization_token}
|
|
39
39
|
request = Request(
|
|
40
40
|
HttpMethod.POST, url, timeout, headers=headers, body=str(body),
|
|
41
41
|
response_content_type=ResponseContentType.JSON,
|
|
42
42
|
)
|
|
43
43
|
response = self._make_call(request, False)
|
|
44
44
|
KameleoonLogger.debug(lambda: f"CALL: AutomationServiceImpl.fetch_access_jwtoken("
|
|
45
|
-
f"
|
|
46
|
-
f"client_secret: '{StringUtils.secret(client_secret)}', "
|
|
45
|
+
f"basic_authorization_token: '{StringUtils.secret(basic_authorization_token)}', "
|
|
47
46
|
f"timeout: {timeout}) -> (response_coroutine)")
|
|
48
47
|
return response
|
{kameleoon_client_python-3.18.0 → kameleoon_client_python-3.19.0}/kameleoon/network/url_provider.py
RENAMED
|
@@ -34,18 +34,22 @@ class UrlProvider:
|
|
|
34
34
|
self.site_code = site_code
|
|
35
35
|
self._data_api_domain = self.DEFAULT_DATA_API_DOMAIN # if remove W0201 error (pylint)
|
|
36
36
|
self.__setup_domains(network_domain)
|
|
37
|
-
|
|
37
|
+
query_builder = self.__make_sdk_sitecode_query_builder()
|
|
38
|
+
self.__sdk_sitecode_query_base = str(query_builder)
|
|
39
|
+
query_builder.append(
|
|
40
|
+
QueryParam(QueryParams.BODY_UA, "true"),
|
|
41
|
+
)
|
|
42
|
+
self.__tracking_query_base = str(query_builder)
|
|
38
43
|
|
|
39
|
-
def
|
|
44
|
+
def __make_sdk_sitecode_query_builder(self) -> QueryBuilder:
|
|
40
45
|
# fmt: off
|
|
41
46
|
query_builder = QueryBuilder(
|
|
42
47
|
QueryParam(QueryParams.SDK_NAME, SdkVersion.NAME),
|
|
43
48
|
QueryParam(QueryParams.SDK_VERSION, SdkVersion.VERSION),
|
|
44
49
|
QueryParam(QueryParams.SITE_CODE, self.site_code),
|
|
45
|
-
QueryParam(QueryParams.BODY_UA, "true"),
|
|
46
50
|
)
|
|
47
51
|
# fmt: on
|
|
48
|
-
return
|
|
52
|
+
return query_builder
|
|
49
53
|
|
|
50
54
|
def __setup_domains(self, network_domain: Optional[str]) -> None:
|
|
51
55
|
"""Updates the domains based on the provided network domain."""
|
|
@@ -73,7 +77,7 @@ class UrlProvider:
|
|
|
73
77
|
|
|
74
78
|
def make_tracking_url(self) -> str:
|
|
75
79
|
"""Constructs the URL for tracking events."""
|
|
76
|
-
return self._DATA_API_URL_FORMAT.format(self._data_api_domain, self._TRACKING_PATH, self.
|
|
80
|
+
return self._DATA_API_URL_FORMAT.format(self._data_api_domain, self._TRACKING_PATH, self.__tracking_query_base)
|
|
77
81
|
|
|
78
82
|
def make_visitor_data_get_url(
|
|
79
83
|
self, visitor_code: str, data_filter: RemoteVisitorDataFilter, is_unique_identifier: bool = False
|
|
@@ -134,4 +138,4 @@ class UrlProvider:
|
|
|
134
138
|
|
|
135
139
|
def make_access_token_url(self) -> str:
|
|
136
140
|
"""Constructs the URL for fetching access tokens."""
|
|
137
|
-
return self._ACCESS_TOKEN_URL_FORMAT.format(self._access_token_domain)
|
|
141
|
+
return self._ACCESS_TOKEN_URL_FORMAT.format(self._access_token_domain) + "?" + self.__sdk_sitecode_query_base
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Unknown condition"""
|
|
2
2
|
from typing import Any
|
|
3
|
+
|
|
4
|
+
from kameleoon.logging.kameleoon_logger import KameleoonLogger
|
|
3
5
|
from kameleoon.targeting.conditions.targeting_condition import TargetingCondition
|
|
4
6
|
|
|
5
7
|
|
|
@@ -11,4 +13,5 @@ class UnknownCondition(TargetingCondition):
|
|
|
11
13
|
"""
|
|
12
14
|
|
|
13
15
|
def check(self, data: Any) -> bool:
|
|
16
|
+
KameleoonLogger.warning("Condition of unknown type '%s' evaluated as true", self.type)
|
|
14
17
|
return True
|