wingify-fme-python-sdk 1.50.0__tar.gz → 1.55.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. {wingify_fme_python_sdk-1.50.0/wingify_fme_python_sdk.egg-info → wingify_fme_python_sdk-1.55.0}/PKG-INFO +1 -1
  2. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/setup.py +2 -2
  3. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/api/get_flag_api.py +61 -1
  4. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/constants/Constants.py +1 -1
  5. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/event_enum.py +1 -0
  6. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/settings/settings_model.py +8 -1
  7. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/resources/debug-messages.json +2 -1
  8. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/impression_util.py +69 -1
  9. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0/wingify_fme_python_sdk.egg-info}/PKG-INFO +1 -1
  10. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/LICENSE +0 -0
  11. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/MANIFEST.in +0 -0
  12. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/NOTICE +0 -0
  13. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/README.md +0 -0
  14. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/requirements-dev.txt +0 -0
  15. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/requirements.txt +0 -0
  16. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/setup.cfg +0 -0
  17. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/vwo/__init__.py +0 -0
  18. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/vwo/vwo.py +0 -0
  19. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/vwo/vwo_builder.py +0 -0
  20. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/vwo/vwo_client.py +0 -0
  21. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/__init__.py +0 -0
  22. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/api/__init__.py +0 -0
  23. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/api/set_attribute_api.py +0 -0
  24. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/api/track_api.py +0 -0
  25. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/constants/__init__.py +0 -0
  26. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/decorators/__init__.py +0 -0
  27. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/decorators/storage_decorator.py +0 -0
  28. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/__init__.py +0 -0
  29. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/api_enum.py +0 -0
  30. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/campaign_type_enum.py +0 -0
  31. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/debug_category_enum.py +0 -0
  32. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/headers_enum.py +0 -0
  33. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/hooks_enum.py +0 -0
  34. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/status_enum.py +0 -0
  35. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/storage_enum.py +0 -0
  36. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/enums/url_enum.py +0 -0
  37. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/Alias.py +0 -0
  38. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/AliasSetResponse.py +0 -0
  39. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/__init__.py +0 -0
  40. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/batch_event_data.py +0 -0
  41. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/__init__.py +0 -0
  42. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/campaign_model.py +0 -0
  43. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/feature_model.py +0 -0
  44. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/holdout_model.py +0 -0
  45. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/impact_campaign_model.py +0 -0
  46. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/metric_model.py +0 -0
  47. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/rule_model.py +0 -0
  48. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/variable_model.py +0 -0
  49. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/campaign/variation_model.py +0 -0
  50. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/gateway_service_model.py +0 -0
  51. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/__init__.py +0 -0
  52. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/campaign_group_schema.py +0 -0
  53. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/campaign_metric_schema.py +0 -0
  54. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/campaign_schema.py +0 -0
  55. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/campaign_variation_schema.py +0 -0
  56. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/empty_object_schema.py +0 -0
  57. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/feature_schema.py +0 -0
  58. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/group_schema.py +0 -0
  59. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/holdout_schema.py +0 -0
  60. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/rule_schema.py +0 -0
  61. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/settings_schema.py +0 -0
  62. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/schemas/variable_schema.py +0 -0
  63. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/settings/__init__.py +0 -0
  64. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/storage/__init__.py +0 -0
  65. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/storage/storage_model.py +0 -0
  66. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/user/__init__.py +0 -0
  67. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/user/context_model.py +0 -0
  68. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/user/context_vwo_model.py +0 -0
  69. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/user/get_flag.py +0 -0
  70. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/vwo_options_model.py +0 -0
  71. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/models/wingify_options_model.py +0 -0
  72. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/__init__.py +0 -0
  73. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/decision_maker/__init__.py +0 -0
  74. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/decision_maker/decision_maker.py +0 -0
  75. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/__init__.py +0 -0
  76. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/core/__init__.py +0 -0
  77. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/core/log_manager.py +0 -0
  78. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/core/log_transport_manager.py +0 -0
  79. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/enums/__init__.py +0 -0
  80. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/enums/log_level_enum.py +0 -0
  81. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/enums/log_level_number_enum.py +0 -0
  82. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/log_message_builder.py +0 -0
  83. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/logger.py +0 -0
  84. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/transports/__init__.py +0 -0
  85. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/logger/transports/console_transport.py +0 -0
  86. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/__init__.py +0 -0
  87. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/client/__init__.py +0 -0
  88. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/client/network_client.py +0 -0
  89. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/handlers/__init__.py +0 -0
  90. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/handlers/request_handler.py +0 -0
  91. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/manager/__init__.py +0 -0
  92. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/manager/network_manager.py +0 -0
  93. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/models/__init__.py +0 -0
  94. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/models/global_request_model.py +0 -0
  95. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/models/request_model.py +0 -0
  96. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/network_layer/models/response_model.py +0 -0
  97. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/__init__.py +0 -0
  98. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/core/__init__.py +0 -0
  99. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/core/segmentation_manager.py +0 -0
  100. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/enums/__init__.py +0 -0
  101. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/enums/segment_operand_regex_enum.py +0 -0
  102. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/enums/segment_operand_value_enum.py +0 -0
  103. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/enums/segment_operator_value_enum.py +0 -0
  104. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/evaluators/__init__.py +0 -0
  105. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/evaluators/segment_evaluator.py +0 -0
  106. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/evaluators/segment_operand_evaluator.py +0 -0
  107. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/utils/__init__.py +0 -0
  108. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/segmentation_evaluator/utils/segment_util.py +0 -0
  109. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/storage/__init__.py +0 -0
  110. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/storage/connector.py +0 -0
  111. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/packages/storage/storage.py +0 -0
  112. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/resources/__init__.py +0 -0
  113. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/resources/error-messages.json +0 -0
  114. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/resources/info-message.json +0 -0
  115. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/resources/trace-messages.json +0 -0
  116. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/resources/warn-messages.json +0 -0
  117. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/__init__.py +0 -0
  118. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/batch_event_queue.py +0 -0
  119. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/campaign_decision_service.py +0 -0
  120. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/hooks_manager.py +0 -0
  121. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/settings_manager.py +0 -0
  122. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/storage_service.py +0 -0
  123. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/services/url_service.py +0 -0
  124. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/__init__.py +0 -0
  125. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/aliasing_util.py +0 -0
  126. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/brand_context.py +0 -0
  127. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/brand_util.py +0 -0
  128. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/campaign_util.py +0 -0
  129. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/data_type_util.py +0 -0
  130. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/debugger_service_util.py +0 -0
  131. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/decision_util.py +0 -0
  132. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/event_util.py +0 -0
  133. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/function_util.py +0 -0
  134. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/gateway_service_util.py +0 -0
  135. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/holdout_util.py +0 -0
  136. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/log_message_util.py +0 -0
  137. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/meg_util.py +0 -0
  138. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/model_utils.py +0 -0
  139. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/network_util.py +0 -0
  140. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/rule_evaluation_util.py +0 -0
  141. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/settings_util.py +0 -0
  142. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/usage_stats_util.py +0 -0
  143. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/utils/uuid_util.py +0 -0
  144. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/vwo_client.py +0 -0
  145. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/wingify.py +0 -0
  146. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/wingify_builder.py +0 -0
  147. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify/wingify_client.py +0 -0
  148. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify_fme_python_sdk.egg-info/SOURCES.txt +0 -0
  149. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify_fme_python_sdk.egg-info/dependency_links.txt +0 -0
  150. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify_fme_python_sdk.egg-info/requires.txt +0 -0
  151. {wingify_fme_python_sdk-1.50.0 → wingify_fme_python_sdk-1.55.0}/wingify_fme_python_sdk.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wingify-fme-python-sdk
3
- Version: 1.50.0
3
+ Version: 1.55.0
4
4
  Summary: Wingify Feature Management and Experimentation SDK for Python
5
5
  Home-page: https://github.com/wingify/vwo-fme-python-sdk
6
6
  Author: Wingify
@@ -46,7 +46,7 @@ _BRAND_METADATA = {
46
46
  },
47
47
  }
48
48
 
49
- _brand = _BRAND_METADATA.get(SDK_BRAND, _BRAND_METADATA["vwo"])
49
+ _brand = _BRAND_METADATA.get(SDK_BRAND, _BRAND_METADATA["wingify"])
50
50
 
51
51
  _all_packages = find_packages(exclude=["tests"])
52
52
  # Both wheels ship wingify (core) + vwo (legacy facade). Customers import one or the other.
@@ -143,7 +143,7 @@ class PostDevelopCommand(develop):
143
143
 
144
144
  setup(
145
145
  name=_brand["name"],
146
- version="1.50.0",
146
+ version="1.55.0",
147
147
  description=_brand["description"],
148
148
  long_description=long_description,
149
149
  long_description_content_type="text/markdown",
@@ -36,6 +36,7 @@ from ..utils.decision_util import evaluate_traffic_and_get_variation
36
36
  from ..utils.impression_util import (
37
37
  send_impression_for_variation_shown_batch,
38
38
  send_impression_for_variation_shown,
39
+ create_and_send_impression_for_usage_tracking,
39
40
  )
40
41
  from ..models.user.get_flag import GetFlag
41
42
  from ..services.storage_service import StorageService
@@ -76,6 +77,9 @@ class GetFlagApi:
76
77
  :param hook_manager: The hook manager to execute hooks.
77
78
  """
78
79
 
80
+ # Flag for usage tracking - false if no variation shown call is sent
81
+ is_variation_shown_fired = False
82
+
79
83
  feature = get_feature_from_key(settings, feature_key)
80
84
  is_enabled = False
81
85
  variables = []
@@ -173,6 +177,15 @@ class GetFlagApi:
173
177
  )
174
178
  else:
175
179
  send_impression_for_variation_shown_batch(holdout_payloads, account_id=settings.get_account_id(), sdk_key=settings.get_sdk_key())
180
+
181
+ # if impression is fired for any of the holdouts, set is_variation_shown_fired to True
182
+ if holdout_payloads and len(holdout_payloads) > 0:
183
+ is_variation_shown_fired = True
184
+
185
+ # Case: User is already part of a holdout (stored decision).
186
+ if settings.get_is_tracking_usage_enabled() and not is_variation_shown_fired:
187
+ create_and_send_impression_for_usage_tracking(settings, feature_key, context)
188
+
176
189
  # Return a disabled flag as user is in persistent holdout
177
190
  return GetFlag(is_enabled=False, variables=[], session_id=context.get_session_id(), uuid=context.get_vwo_uuid())
178
191
  if stored_data and stored_data.get("experimentVariationId"):
@@ -194,7 +207,19 @@ class GetFlagApi:
194
207
  )
195
208
  decision["isUserPartOfCampaign"] = True
196
209
  # send network calls for holdouts that are newly added in settings and are not present in storage
197
- send_network_calls_for_not_in_holdouts(settings, feature, context, decision, stored_data, storage_service)
210
+ # Calculate the initial size of not_in_holdout_id
211
+ initial_size = len(stored_data.get("notInHoldoutId") or []) if stored_data else 0
212
+ # send network calls for not_in_holdout_id
213
+ updated_not_in_holdouts = send_network_calls_for_not_in_holdouts(settings, feature, context, decision, stored_data, storage_service)
214
+ # if variationShown event is fired, set is_variation_shown_fired to True - Optimization for newly added holdouts
215
+ if updated_not_in_holdouts and len(updated_not_in_holdouts) > initial_size:
216
+ is_variation_shown_fired = True
217
+
218
+ # Case: Feature found in storage
219
+ # Send usage tracking for cached experiment decision if usage tracking is enabled
220
+ if settings.get_is_tracking_usage_enabled() and not is_variation_shown_fired:
221
+ create_and_send_impression_for_usage_tracking(settings, feature_key, context)
222
+
198
223
  return GetFlag(is_enabled=True, variables=variation.get_variables(), session_id=context.get_session_id(), uuid=context.get_vwo_uuid())
199
224
  elif (
200
225
  stored_data
@@ -217,7 +242,10 @@ class GetFlagApi:
217
242
  decision["isUserPartOfCampaign"] = True
218
243
  # network calls for holdouts that are newly added in settings and are not present in storage
219
244
  # and return the updated not in holdout ids
245
+ initial_size = len(stored_data.get("notInHoldoutId") or []) if stored_data else 0
220
246
  updated_not_in_holdout_ids = send_network_calls_for_not_in_holdouts(settings, feature, context, decision, stored_data, storage_service)
247
+ if updated_not_in_holdout_ids and len(updated_not_in_holdout_ids) > initial_size:
248
+ is_variation_shown_fired = True
221
249
  # push the updated not in holdout ids to the notInHoldoutIds array
222
250
  notInHoldoutIds.extend(updated_not_in_holdout_ids)
223
251
 
@@ -236,6 +264,12 @@ class GetFlagApi:
236
264
  if feature is None:
237
265
  LogManager.get_instance().error_log("FEATURE_NOT_FOUND", data={"featureKey": feature_key}, debug_data = debug_event_props)
238
266
  is_enabled = False
267
+
268
+ # Case: Feature not found
269
+ # If usage tracking is enabled, send usage tracking impression
270
+ if settings.get_is_tracking_usage_enabled() and not is_variation_shown_fired:
271
+ create_and_send_impression_for_usage_tracking(settings, feature_key, context)
272
+
239
273
  return GetFlag(is_enabled=is_enabled, variables=variables, session_id=context.get_session_id(), uuid=context.get_vwo_uuid())
240
274
 
241
275
  if context.get_session_id() is None:
@@ -315,6 +349,9 @@ class GetFlagApi:
315
349
  else:
316
350
  batchPayload.extend(holdout_payloads)
317
351
 
352
+ if holdout_payloads and len(holdout_payloads) > 0:
353
+ is_variation_shown_fired = True
354
+
318
355
  roll_out_rules = get_specific_rules_based_on_type(
319
356
  feature, CampaignTypeEnum.ROLLOUT.value
320
357
  )
@@ -390,9 +427,13 @@ class GetFlagApi:
390
427
  and payload is not None
391
428
  and len(payload) > 0
392
429
  ):
430
+ # set is_variation_shown_fired to true as the rollout impression is sent
431
+ is_variation_shown_fired = True
393
432
  send_impression_for_variation_shown(payload, context)
394
433
  else:
395
434
  if payload is not None and len(payload) > 0:
435
+ # set is_variation_shown_fired to true as the rollout impression is sent
436
+ is_variation_shown_fired = True
396
437
  batchPayload.append(payload)
397
438
 
398
439
  if not roll_out_rules:
@@ -435,9 +476,15 @@ class GetFlagApi:
435
476
  and payload is not None
436
477
  and len(payload) > 0
437
478
  ):
479
+ # set is_variation_shown_fired to true as the experiment impression is sent (for whitelisted user)
480
+ # this prevents sending usage tracking impression for the experiment campaign when checked at the bottom
481
+ is_variation_shown_fired = True
438
482
  send_impression_for_variation_shown(payload, context)
439
483
  else:
440
484
  if payload is not None and len(payload) > 0:
485
+ # set is_variation_shown_fired to true as the experiment impression is sent (for whitelisted user)
486
+ # this prevents sending usage tracking impression for the experiment campaign when checked at the bottom
487
+ is_variation_shown_fired = True
441
488
  batchPayload.append(payload)
442
489
 
443
490
  is_enabled = True
@@ -481,9 +528,13 @@ class GetFlagApi:
481
528
  and payload is not None
482
529
  and len(payload) > 0
483
530
  ):
531
+ # set is_variation_shown_fired to true as the experiment impression is sent.
532
+ is_variation_shown_fired = True
484
533
  send_impression_for_variation_shown(payload, context)
485
534
  else:
486
535
  if payload is not None and len(payload) > 0:
536
+ # set is_variation_shown_fired to true as the experiment impression is sent.
537
+ is_variation_shown_fired = True
487
538
  batchPayload.append(payload)
488
539
 
489
540
  if is_enabled:
@@ -545,9 +596,13 @@ class GetFlagApi:
545
596
  and payload is not None
546
597
  and len(payload) > 0
547
598
  ):
599
+ # set is_variation_shown_fired to true as the impact analysis impression is sent.
600
+ is_variation_shown_fired = True
548
601
  send_impression_for_variation_shown(payload, context)
549
602
  else:
550
603
  if payload is not None and len(payload) > 0:
604
+ # set is_variation_shown_fired to true as the impact analysis impression is sent.
605
+ is_variation_shown_fired = True
551
606
  batchPayload.append(payload)
552
607
 
553
608
  if not SettingsManager.get_instance().is_gateway_service_provided:
@@ -555,6 +610,11 @@ class GetFlagApi:
555
610
  batchPayload, settings.get_account_id(), settings.get_sdk_key()
556
611
  )
557
612
 
613
+ # Send usage tracking call when no primary variationShown event was dispatched.
614
+ # If a primary event was fired, the server already has the usage tracking signal.
615
+ if settings.get_is_tracking_usage_enabled() and not is_variation_shown_fired:
616
+ create_and_send_impression_for_usage_tracking(settings, feature_key, context)
617
+
558
618
  return GetFlag(is_enabled=is_enabled, variables=variables, session_id=context.get_session_id(), uuid=context.get_vwo_uuid())
559
619
 
560
620
  def _update_integrations_decision_object(
@@ -17,7 +17,7 @@ class Constants:
17
17
  # TODO: read from setup.py
18
18
  sdk_meta = {
19
19
  "name": "vwo-fme-python-sdk",
20
- "version": "1.50.0",
20
+ "version": "1.55.0",
21
21
  }
22
22
 
23
23
  SDK_VERSION = sdk_meta["version"]
@@ -23,3 +23,4 @@ class EventEnum(Enum):
23
23
  SDK_INIT_EVENT = "vwo_fmeSdkInit"
24
24
  USAGE_STATS = "vwo_sdkUsageStats"
25
25
  DEBUGGER_EVENT = "vwo_sdkDebug"
26
+ TRACK_USAGE = "vwo_feTrackUsage"
@@ -36,6 +36,7 @@ class SettingsModel:
36
36
  self._poll_interval = data.get("pollInterval", Constants.POLLING_INTERVAL)
37
37
  self._is_web_connectivity_enabled = data.get("isWebConnectivityEnabled", True)
38
38
  self._holdouts = [HoldoutModel(h) for h in data.get("holdouts", [])]
39
+ self._is_tracking_usage_enabled = data.get("isMAU", False)
39
40
 
40
41
  # Getter methods for accessing private attributes
41
42
  def get_features(self) -> List[FeatureModel]:
@@ -100,4 +101,10 @@ class SettingsModel:
100
101
  self._holdouts = value
101
102
 
102
103
  def get_holdouts(self) -> List[HoldoutModel]:
103
- return self._holdouts if isinstance(self._holdouts, list) else []
104
+ return self._holdouts if isinstance(self._holdouts, list) else []
105
+
106
+ def get_is_tracking_usage_enabled(self) -> bool:
107
+ return self._is_tracking_usage_enabled
108
+
109
+ def set_is_tracking_usage_enabled(self, value: bool):
110
+ self._is_tracking_usage_enabled = value
@@ -16,5 +16,6 @@
16
16
  "HOLDOUT_SEGMENTATION_FAIL": "User ID: {userId} does not qualify segmentation for Holdout: {holdoutGroupName}",
17
17
  "HOLDOUT_SHOULD_NOT_EXCLUDE_USER": "User ID: {userId} is not part of Holdout: {holdoutGroupName} for feature: {featureKey}",
18
18
  "PART_OF_HOLDOUT_IN_MEG": "MEG: User ID:{userId} is part of holdout: {holdoutId} for feature: {featureKey}",
19
- "HOLDOUT_SKIP_EVALUATION": "Skip holdout reevaluation for holdout ID: {holdoutId} because {reason}"
19
+ "HOLDOUT_SKIP_EVALUATION": "Skip holdout reevaluation for holdout ID: {holdoutId} because {reason}",
20
+ "IMPRESSION_FOR_TRACK_USAGE": "Impression built for vwo_feTrackUsage({brand} standard event for tracking usage) event having Account ID:{accountId}, User ID:{userId}, and feature key:{featureKey}"
20
21
  }
@@ -80,4 +80,72 @@ def send_impression_for_variation_shown_batch(
80
80
  network_instance.execute_in_background(send_batch_request)
81
81
  else:
82
82
  # execute the request immediately
83
- send_batch_request()
83
+ send_batch_request()
84
+
85
+
86
+ def create_and_send_impression_for_usage_tracking(
87
+ settings, feature_key: str, context: ContextModel
88
+ ):
89
+ """
90
+ Creates and sends an impression for usage tracking.
91
+
92
+ This function is used to send a tracking event to the server when a feature flag
93
+ is evaluated but no primary `variation_shown` event is dispatched (e.g., when serving
94
+ cached decisions from storage, or when the flag is not found).
95
+
96
+ :param settings: The settings file containing the account settings.
97
+ :param feature_key: The feature key for which usage is being tracked.
98
+ :param context: The ContextModel object containing user and session context.
99
+ """
100
+ from ..wingify_client import WingifyClient as VWOClient
101
+ from ..utils.network_util import _get_event_base_payload
102
+ from ..packages.logger.core.log_manager import LogManager
103
+ from ..utils.log_message_util import debug_messages
104
+ from ..utils.function_util import get_current_unix_timestamp_in_millis
105
+ from ..utils.brand_util import get_sdk_name
106
+ from ..services.settings_manager import SettingsManager
107
+
108
+ user_id = context.get_id()
109
+
110
+ properties = _get_event_base_payload(
111
+ settings=settings,
112
+ user_id=user_id,
113
+ event_name=EventEnum.TRACK_USAGE.value,
114
+ visitor_user_agent=context.get_user_agent(),
115
+ ip_address=context.get_ip_address(),
116
+ )
117
+
118
+ if context.get_session_id() is not None and context.get_session_id() != 0:
119
+ properties["d"]["sessionId"] = context.get_session_id()
120
+
121
+ # if uuid is provided in the context, use it, otherwise generate a new one
122
+ if context.get_vwo_uuid() is not None and context.get_vwo_uuid() != "":
123
+ properties["d"]["msgId"] = f"{context.get_vwo_uuid()}-{get_current_unix_timestamp_in_millis()}"
124
+ properties["d"]["visId"] = context.get_vwo_uuid()
125
+
126
+ LogManager.get_instance().debug(
127
+ debug_messages.get("IMPRESSION_FOR_TRACK_USAGE").format(
128
+ brand=get_sdk_name(SettingsManager.get_instance().is_via_vwo),
129
+ accountId=settings.get_account_id(),
130
+ userId=user_id,
131
+ featureKey=feature_key
132
+ )
133
+ )
134
+
135
+ # Note: id, variation, isFirst are not set!
136
+
137
+ vwo_instance = VWOClient.get_instance()
138
+
139
+ # Get base properties for the event
140
+ base_properties = get_events_base_properties(
141
+ EventEnum.TRACK_USAGE.value,
142
+ visitor_user_agent=context.get_user_agent(),
143
+ ip_address=context.get_ip_address(),
144
+ )
145
+
146
+ if vwo_instance.batch_event_queue is not None:
147
+ # Enqueue the event to the batch queue
148
+ vwo_instance.batch_event_queue.enqueue(properties)
149
+ else:
150
+ # Send the event immediately if batch events are not enabled
151
+ send_post_api_request(base_properties, properties, user_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wingify-fme-python-sdk
3
- Version: 1.50.0
3
+ Version: 1.55.0
4
4
  Summary: Wingify Feature Management and Experimentation SDK for Python
5
5
  Home-page: https://github.com/wingify/vwo-fme-python-sdk
6
6
  Author: Wingify