statsig-python-core 0.20.1rc2607140134__tar.gz → 0.20.2__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 (381) hide show
  1. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/Cargo.lock +6 -6
  2. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/Cargo.toml +1 -1
  3. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/PKG-INFO +1 -1
  4. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/statsig.py +11 -1
  5. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/statsig_python_core.pyi +1 -0
  6. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/statsig_types.py +53 -1
  7. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/pyo_utils.rs +1 -4
  8. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/statsig_base_py.rs +21 -4
  9. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/statsig_options_py.rs +2 -0
  10. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/statsig_persistent_storage_override_adapter_py.rs +2 -6
  11. statsig_python_core-0.20.2/statsig-pyo3/tests/test_get_experiment_groups.py +89 -0
  12. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/Cargo.toml +1 -1
  13. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/country_lookup.rs +4 -4
  14. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/__tests__/test_ua_parser_os.rs +10 -0
  15. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/tokenizer.rs +6 -0
  16. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/ua_parser.rs +4 -4
  17. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/dynamic_configs_processor.rs +3 -3
  18. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/gcir_options.rs +9 -0
  19. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/gcir_process_iter.rs +1 -1
  20. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/param_stores_processor.rs +1 -5
  21. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/target_app_id_utils.rs +16 -13
  22. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/instance_registry.rs +3 -3
  23. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/mod.rs +3 -1
  24. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/statsig_http_specs_adapter.rs +591 -22
  25. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig.rs +140 -82
  26. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_metadata.rs +1 -1
  27. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_options.rs +22 -0
  28. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_types.rs +36 -3
  29. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/statsig_user_internal.rs +1 -4
  30. statsig_python_core-0.20.2/statsig-rust/tests/data/dcs_target_app_filtering.json +192 -0
  31. statsig_python_core-0.20.2/statsig-rust/tests/data/dcs_target_app_filtering_hashed_keys.json +65 -0
  32. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/test_must_pass_user_agents.txt +3 -1
  33. statsig_python_core-0.20.2/statsig-rust/tests/gcir_target_app_tests.rs +185 -0
  34. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/gcir_tests.rs +1 -0
  35. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_tests.rs +99 -0
  36. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/__init__.py +0 -0
  37. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/data_store.py +0 -0
  38. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/error_boundary.py +0 -0
  39. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/observability_client.py +0 -0
  40. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/output_logger_provider.py +0 -0
  41. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/persistent_storage.py +0 -0
  42. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/py.typed +0 -0
  43. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/py_src/statsig_python_core/requirements.txt +0 -0
  44. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/pyproject.toml +0 -0
  45. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/Cargo.toml +0 -0
  46. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/README.md +0 -0
  47. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/build.rs +0 -0
  48. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/src/lib.rs +0 -0
  49. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/src/mock_forward_proxy.rs +0 -0
  50. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/src/protos/statsig_forward_proxy.proto +0 -0
  51. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/src/statsig_forward_proxy.rs +0 -0
  52. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/src/statsig_grpc_client.rs +0 -0
  53. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-grpc/src/statsig_grpc_err.rs +0 -0
  54. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/.github/workflows/CI.yml +0 -0
  55. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/.gitignore +0 -0
  56. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/Cargo.toml +0 -0
  57. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/README.md +0 -0
  58. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/bin/stub_gen.rs +0 -0
  59. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/data_store_base_py.rs +0 -0
  60. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/interned_store_py.rs +0 -0
  61. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/lib.rs +0 -0
  62. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/observability_client_base_py.rs +0 -0
  63. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/output_logger_provider_base_py.rs +0 -0
  64. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/raw_evaluation_compat_py.rs +0 -0
  65. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/safe_gil.rs +0 -0
  66. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/statsig_metadata_py.rs +0 -0
  67. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/statsig_types_py.rs +0 -0
  68. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/statsig_user_py.rs +0 -0
  69. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/unit_id_py.rs +0 -0
  70. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/src/valid_primitives_py.rs +0 -0
  71. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/fork_runner.py +0 -0
  72. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/mock_output_logger.py +0 -0
  73. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/mock_scrapi.py +0 -0
  74. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/profile_util.py +0 -0
  75. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/shutdown_sub_proc.py +0 -0
  76. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_data_store.py +0 -0
  77. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_error_boundary.py +0 -0
  78. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_experiment_group_targeting.py +0 -0
  79. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_experiment_serialization.py +0 -0
  80. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_exposure_logging.py +0 -0
  81. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_feature_gate_serialization.py +0 -0
  82. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_forking.py +0 -0
  83. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_get_autotune_list.py +0 -0
  84. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_get_dynamic_config.py +0 -0
  85. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_initialize_with_details.py +0 -0
  86. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_interned_store_preload.py +0 -0
  87. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_layer_param_exposure_sampling.py +0 -0
  88. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_layer_serialization.py +0 -0
  89. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_observability_client.py +0 -0
  90. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_output_logger_provider.py +0 -0
  91. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_override_adapter.py +0 -0
  92. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_performance.py +0 -0
  93. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_sec_expo_as_primary.py +0 -0
  94. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_shared_statsig.py +0 -0
  95. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_shutdown.py +0 -0
  96. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_statsig.py +0 -0
  97. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_statsig_options.py +0 -0
  98. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_statsig_user.py +0 -0
  99. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_statsig_user_json_serialization.py +0 -0
  100. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_statsig_user_none_fields.py +0 -0
  101. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_statsig_user_pickle.py +0 -0
  102. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/test_user_exposure_e2e.py +0 -0
  103. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-pyo3/tests/utils.py +0 -0
  104. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/build.rs +0 -0
  105. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/examples/eval_contention_bench.rs +0 -0
  106. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/examples/intern_contention_bench.rs +0 -0
  107. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/resources/ip_supalite.table +0 -0
  108. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/resources/ua_parser_regex.yaml +0 -0
  109. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/resources/ua_parser_regex_lite.yaml +0 -0
  110. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/__tests__/interned_string_tests.rs +0 -0
  111. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/__tests__/mod.rs +0 -0
  112. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/__tests__/spec_store_tests.rs +0 -0
  113. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/compression/compression_helper.rs +0 -0
  114. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/compression/mod.rs +0 -0
  115. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/console_capture/console_capture_handler.rs +0 -0
  116. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/console_capture/console_capture_instances.rs +0 -0
  117. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/console_capture/console_capture_options.rs +0 -0
  118. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/console_capture/console_log_line_levels.rs +0 -0
  119. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/console_capture/mod.rs +0 -0
  120. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/data_store_interface.rs +0 -0
  121. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/dcs_str.rs +0 -0
  122. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/__tests__/dynamic_returnable_tests.rs +0 -0
  123. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/__tests__/mod.rs +0 -0
  124. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/__tests__/rkyv_value_tests.rs +0 -0
  125. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/cmab_evaluator.rs +0 -0
  126. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/compare_arrays.rs +0 -0
  127. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/compare_numbers.rs +0 -0
  128. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/compare_str_with_regex.rs +0 -0
  129. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/compare_strings_in_array.rs +0 -0
  130. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/compare_time.rs +0 -0
  131. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/compare_versions.rs +0 -0
  132. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/comparisons/mod.rs +0 -0
  133. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/dynamic_returnable.rs +0 -0
  134. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/dynamic_string.rs +0 -0
  135. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/dynamic_value.rs +0 -0
  136. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluation_details.rs +0 -0
  137. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluation_types.rs +0 -0
  138. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluation_types_initialize_v2.rs +0 -0
  139. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluation_types_v2.rs +0 -0
  140. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluator.rs +0 -0
  141. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluator_context.rs +0 -0
  142. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluator_result.rs +0 -0
  143. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/evaluator_value.rs +0 -0
  144. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/get_unit_id.rs +0 -0
  145. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/mod.rs +0 -0
  146. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/rkyv_value.rs +0 -0
  147. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/secondary_exposure_key.rs +0 -0
  148. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/first_party_ua_parser.rs +0 -0
  149. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/mod.rs +0 -0
  150. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/__tests__/mod.rs +0 -0
  151. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/__tests__/test_helpers.rs +0 -0
  152. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/__tests__/test_tokenizer.rs +0 -0
  153. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/__tests__/test_ua_parser_browser.rs +0 -0
  154. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/mod.rs +0 -0
  155. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/ua_parser.rs +0 -0
  156. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/statsig_uaparser/window_iter.rs +0 -0
  157. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/evaluation/user_agent_parsing/third_party_ua_parser.rs +0 -0
  158. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_emitter/statsig_event_emitter_tests.rs +0 -0
  159. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_logger.rs +0 -0
  160. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_logger_constants.rs +0 -0
  161. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_logger_ops_stats.rs +0 -0
  162. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/batch.rs +0 -0
  163. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/mod.rs +0 -0
  164. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queue.rs +0 -0
  165. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_config_expo.rs +0 -0
  166. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_event.rs +0 -0
  167. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_experiment_expo.rs +0 -0
  168. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_expo.rs +0 -0
  169. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_gate_expo.rs +0 -0
  170. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_layer_param_expo.rs +0 -0
  171. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_passthrough.rs +0 -0
  172. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/event_queue/queued_secondary_expo.rs +0 -0
  173. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/exposure_sampling.rs +0 -0
  174. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/exposure_utils.rs +0 -0
  175. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/flush_interval.rs +0 -0
  176. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/flush_type.rs +0 -0
  177. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/mod.rs +0 -0
  178. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/sec_expo_as_primary_experiment.rs +0 -0
  179. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/statsig_event.rs +0 -0
  180. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging/statsig_event_internal.rs +0 -0
  181. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging_adapter/event_logging_adapter_trait.rs +0 -0
  182. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging_adapter/log_event_payload.rs +0 -0
  183. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging_adapter/mod.rs +0 -0
  184. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging_adapter/statsig_http_event_logging_adapter.rs +0 -0
  185. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/event_logging_adapter/statsig_local_file_event_logging_adapter.rs +0 -0
  186. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/feature_gates_processor.rs +0 -0
  187. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/gcir_formatter.rs +0 -0
  188. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/layer_configs_processor.rs +0 -0
  189. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/mod.rs +0 -0
  190. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/gcir/stringify_sec_exposures.rs +0 -0
  191. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/global_configs.rs +0 -0
  192. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/hashing/ahash.rs +0 -0
  193. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/hashing/djb2.rs +0 -0
  194. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/hashing/hash_util.rs +0 -0
  195. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/hashing/memo_sha_256.rs +0 -0
  196. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/hashing/mod.rs +0 -0
  197. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/id_lists_adapter/id_list.rs +0 -0
  198. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/id_lists_adapter/id_lists_adapter_trait.rs +0 -0
  199. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/id_lists_adapter/mod.rs +0 -0
  200. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/id_lists_adapter/statsig_http_id_lists_adapter.rs +0 -0
  201. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/init_details.rs +0 -0
  202. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/initialize_evaluations_response.rs +0 -0
  203. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/initialize_response.rs +0 -0
  204. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/initialize_v2_response.rs +0 -0
  205. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_string.rs +0 -0
  206. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_values/__tests__/interned_store_eval_value_tests.rs +0 -0
  207. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_values/__tests__/interned_store_returnable_tests.rs +0 -0
  208. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_values/__tests__/interned_store_string_tests.rs +0 -0
  209. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_values/__tests__/mod.rs +0 -0
  210. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_values/interned_store.rs +0 -0
  211. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/interned_values/mod.rs +0 -0
  212. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/lib.rs +0 -0
  213. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/logging_utils.rs +0 -0
  214. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/macros.rs +0 -0
  215. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/__tests__/mod.rs +0 -0
  216. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/__tests__/response_data_tests.rs +0 -0
  217. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/http_types.rs +0 -0
  218. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/mod.rs +0 -0
  219. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/network_client.rs +0 -0
  220. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/network_error.rs +0 -0
  221. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/providers/mod.rs +0 -0
  222. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/providers/net_provider_global.rs +0 -0
  223. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/providers/net_provider_noop.rs +0 -0
  224. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/providers/net_provider_reqwest.rs +0 -0
  225. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/networking/proxy_config.rs +0 -0
  226. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/observability/console_capture_observer.rs +0 -0
  227. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/observability/diagnostics_observer.rs +0 -0
  228. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/observability/mod.rs +0 -0
  229. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/observability/observability_client_adapter.rs +0 -0
  230. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/observability/ops_stats.rs +0 -0
  231. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/observability/sdk_errors_observer.rs +0 -0
  232. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/output_logger.rs +0 -0
  233. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/override_adapter/mod.rs +0 -0
  234. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/override_adapter/override_adapter_trait.rs +0 -0
  235. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/override_adapter/statsig_local_override_adapter.rs +0 -0
  236. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/persistent_storage/__tests__/mod.rs +0 -0
  237. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/persistent_storage/__tests__/sticky_values_serialization_tests.rs +0 -0
  238. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/persistent_storage/mod.rs +0 -0
  239. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/persistent_storage/persistent_storage_trait.rs +0 -0
  240. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/persistent_storage/persistent_values_manager.rs +0 -0
  241. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_diagnostics/diagnostics.rs +0 -0
  242. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_diagnostics/diagnostics_utils.rs +0 -0
  243. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_diagnostics/marker.rs +0 -0
  244. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_diagnostics/mod.rs +0 -0
  245. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_event_emitter/event_emitter.rs +0 -0
  246. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_event_emitter/event_emitter_tests.rs +0 -0
  247. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_event_emitter/event_types.rs +0 -0
  248. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/sdk_event_emitter/mod.rs +0 -0
  249. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/spec_store.rs +0 -0
  250. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/config_spec_background_sync_metrics.rs +0 -0
  251. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/response_format.rs +0 -0
  252. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/specs_adapter_trait.rs +0 -0
  253. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/statsig_bootstrap_specs_adapter.rs +0 -0
  254. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/statsig_customized_specs_adapter.rs +0 -0
  255. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/statsig_data_store_specs_adapter.rs +0 -0
  256. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/statsig_grpc_specs_adapter.rs +0 -0
  257. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_adapter/statsig_local_file_specs_adapter.rs +0 -0
  258. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/__tests__/mod.rs +0 -0
  259. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/__tests__/proto_specs_syncing_tests.rs +0 -0
  260. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/__tests__/proto_specs_unknown_tests.rs +0 -0
  261. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/__tests__/proto_specs_vs_json_tests.rs +0 -0
  262. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/__tests__/proto_stream_reader_tests.rs +0 -0
  263. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/cmab_types.rs +0 -0
  264. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/explicit_params.rs +0 -0
  265. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/mod.rs +0 -0
  266. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/param_store_types.rs +0 -0
  267. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/proto_specs.rs +0 -0
  268. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/proto_stream_reader.rs +0 -0
  269. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/spec_types.rs +0 -0
  270. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/specs_hash_map.rs +0 -0
  271. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/specs_response/statsig_config_specs.rs +0 -0
  272. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_core_api_options.rs +0 -0
  273. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_err.rs +0 -0
  274. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_global.rs +0 -0
  275. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_runtime.rs +0 -0
  276. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_type_factories.rs +0 -0
  277. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/statsig_types_raw.rs +0 -0
  278. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/into_optional.rs +0 -0
  279. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/mod.rs +0 -0
  280. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/statsig_user.rs +0 -0
  281. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/statsig_user_builder.rs +0 -0
  282. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/statsig_user_loggable.rs +0 -0
  283. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/unit_id.rs +0 -0
  284. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/user/user_data.rs +0 -0
  285. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/src/utils/mod.rs +0 -0
  286. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/check_gate_concurrency_bench.rs +0 -0
  287. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/check_gate_tests.rs +0 -0
  288. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/customized_specs_adapter_tests.rs +0 -0
  289. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/big_number_dcs.json +0 -0
  290. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/check_gate_perf_dcs.json +0 -0
  291. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/company_id_list +0 -0
  292. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_error.json +0 -0
  293. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_missing_gates.json +0 -0
  294. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_non_case_sensitive.json +0 -0
  295. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_user_agent_versions.json +0 -0
  296. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_with_analytical_exposure_sampling.json +0 -0
  297. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_with_checksum.json +0 -0
  298. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_with_sampling.json +0 -0
  299. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/dcs_with_sdk_configs.json +0 -0
  300. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/demo_proj_dcs.json +0 -0
  301. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/demo_proj_dcs.pb.br +0 -0
  302. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/eval_proj_dcs.json +0 -0
  303. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/eval_proj_dcs.pb.br +0 -0
  304. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/get_id_lists.json +0 -0
  305. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/perf_proj_dcs.json +0 -0
  306. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/perf_proj_dcs.pb.br +0 -0
  307. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/shared_dict_dict_only.json +0 -0
  308. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/shared_dict_original_dcs.json +0 -0
  309. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/shared_dict_response_uncompressed.json +0 -0
  310. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/shared_dict_response_with_dict.json +0 -0
  311. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/shared_dict_response_without_dict.json +0 -0
  312. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/test_user_agents.txt +0 -0
  313. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/ua_string_cases.json +0 -0
  314. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data/unknown_enum.pb.br +0 -0
  315. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data_store_bytes_adapter_tests.rs +0 -0
  316. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data_store_json_bytes_tests.rs +0 -0
  317. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data_store_json_only_no_bytes_methods_tests.rs +0 -0
  318. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data_store_lock_tests.rs +0 -0
  319. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/data_store_proto_bytes_tests.rs +0 -0
  320. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/direct_gcir_tests.rs +0 -0
  321. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/dynamic_string_tests.rs +0 -0
  322. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/dynamic_value_tests.rs +0 -0
  323. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/evaluation_details_tests.rs +0 -0
  324. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/evaluator_value_tests.rs +0 -0
  325. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/event_logger_failing_flush_tests.rs +0 -0
  326. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/event_logger_flush_tests.rs +0 -0
  327. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/event_logger_high_qps_tests.rs +0 -0
  328. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/event_logger_usage_tests.rs +0 -0
  329. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/expected_evaluation_tests.rs +0 -0
  330. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/exposure_sampling_key_tests.rs +0 -0
  331. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/exposure_tests.rs +0 -0
  332. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/flushing_tests.rs +0 -0
  333. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/gate_inversion_eval_tests.rs +0 -0
  334. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/global_configs_test.rs +0 -0
  335. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/grpc_specs_adapter_tests.rs +0 -0
  336. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/hash_util_evaluation_hash_tests.rs +0 -0
  337. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/http_specs_adapter_tests.rs +0 -0
  338. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/initialize_timeout_test.rs +0 -0
  339. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/instance_registry_tests.rs +0 -0
  340. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/layer_serialization_tests.rs +0 -0
  341. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/list_methods_tests.rs +0 -0
  342. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/memory_leak_per_request_users_tests.rs +0 -0
  343. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/network_client_streaming_tests.rs +0 -0
  344. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/network_client_tests.rs +0 -0
  345. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/network_failure_tests.rs +0 -0
  346. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/observability_client_usage_tests.rs +0 -0
  347. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/output_logger_tests.rs +0 -0
  348. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/override_adapter_tests.rs +0 -0
  349. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/perf_tests.rs +0 -0
  350. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/persistent_storage_enforce_tests.rs +0 -0
  351. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/proto_specs_usage_tests.rs +0 -0
  352. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/spec_store_lock_tests.rs +0 -0
  353. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/spec_types_tests.rs +0 -0
  354. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_disable_network_tests.rs +0 -0
  355. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_environment_tests.rs +0 -0
  356. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_event_emitter_usage_test.rs +0 -0
  357. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_global_tests.rs +0 -0
  358. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_local_file_event_logging_adapter_tests.rs +0 -0
  359. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_local_file_specs_adapter_tests.rs +0 -0
  360. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_options_tests.rs +0 -0
  361. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_shared_tests.rs +0 -0
  362. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_user_builder_tests.rs +0 -0
  363. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_user_field_accessor_tests.rs +0 -0
  364. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_user_internal_tests.rs +0 -0
  365. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_user_loggable_tests.rs +0 -0
  366. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/statsig_user_tests.rs +0 -0
  367. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/syncing_network_failure_tests.rs +0 -0
  368. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/typed_getters_tests.rs +0 -0
  369. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/ua_parser_util_test.rs +0 -0
  370. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/user_agent_tests_first_party.rs +0 -0
  371. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/user_json_tests.rs +0 -0
  372. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/env_var_guard.rs +0 -0
  373. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/helpers.rs +0 -0
  374. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_data_store.rs +0 -0
  375. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_event_logging_adapter.rs +0 -0
  376. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_log_provider.rs +0 -0
  377. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_observability_client.rs +0 -0
  378. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_scrapi.rs +0 -0
  379. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_specs_adapter.rs +0 -0
  380. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mock_specs_listener.rs +0 -0
  381. {statsig_python_core-0.20.1rc2607140134 → statsig_python_core-0.20.2}/statsig-rust/tests/utils/mod.rs +0 -0
@@ -2902,7 +2902,7 @@ dependencies = [
2902
2902
 
2903
2903
  [[package]]
2904
2904
  name = "sigstat-grpc"
2905
- version = "0.20.1-rc.2607140134"
2905
+ version = "0.20.2"
2906
2906
  dependencies = [
2907
2907
  "async-trait",
2908
2908
  "chrono",
@@ -2994,7 +2994,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
2994
2994
 
2995
2995
  [[package]]
2996
2996
  name = "statsig-node"
2997
- version = "0.20.1-rc.2607140134"
2997
+ version = "0.20.2"
2998
2998
  dependencies = [
2999
2999
  "async-trait",
3000
3000
  "napi",
@@ -3009,7 +3009,7 @@ dependencies = [
3009
3009
 
3010
3010
  [[package]]
3011
3011
  name = "statsig-pyo3"
3012
- version = "0.20.1-rc.2607140134"
3012
+ version = "0.20.2"
3013
3013
  dependencies = [
3014
3014
  "async-trait",
3015
3015
  "lazy_static",
@@ -3024,7 +3024,7 @@ dependencies = [
3024
3024
 
3025
3025
  [[package]]
3026
3026
  name = "statsig-rust"
3027
- version = "0.20.1-rc.2607140134"
3027
+ version = "0.20.2"
3028
3028
  dependencies = [
3029
3029
  "ahash",
3030
3030
  "arc-swap",
@@ -3075,7 +3075,7 @@ dependencies = [
3075
3075
 
3076
3076
  [[package]]
3077
3077
  name = "statsig_elixir"
3078
- version = "0.20.1-rc.2607140134"
3078
+ version = "0.20.2"
3079
3079
  dependencies = [
3080
3080
  "async-trait",
3081
3081
  "parking_lot",
@@ -3088,7 +3088,7 @@ dependencies = [
3088
3088
 
3089
3089
  [[package]]
3090
3090
  name = "statsig_ffi"
3091
- version = "0.20.1-rc.2607140134"
3091
+ version = "0.20.2"
3092
3092
  dependencies = [
3093
3093
  "async-trait",
3094
3094
  "cbindgen",
@@ -19,7 +19,7 @@ exclude = [
19
19
  [workspace.package]
20
20
  edition = "2021"
21
21
  license = "ISC"
22
- version = "0.20.1-rc.2607140134"
22
+ version = "0.20.2"
23
23
  homepage = "https://statsig.com/"
24
24
  authors = ["Statsig", "Daniel Loomb <daniel@statsig.com>"]
25
25
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statsig_python_core
3
- Version: 0.20.1rc2607140134
3
+ Version: 0.20.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -12,7 +12,13 @@ from statsig_python_core import (
12
12
  )
13
13
  from typing import Optional
14
14
  from .error_boundary import ErrorBoundary
15
- from .statsig_types import DynamicConfig, FeatureGate, Experiment, Layer
15
+ from .statsig_types import (
16
+ DynamicConfig,
17
+ Experiment,
18
+ ExperimentGroupsResult,
19
+ FeatureGate,
20
+ Layer,
21
+ )
16
22
  import atexit
17
23
 
18
24
 
@@ -126,6 +132,10 @@ class Statsig(StatsigBasePy):
126
132
  )
127
133
  return Experiment(experiment_name, raw)
128
134
 
135
+ def get_experiment_groups(self, experiment_name: str) -> ExperimentGroupsResult:
136
+ raw = super()._INTERNAL_get_experiment_groups(experiment_name)
137
+ return ExperimentGroupsResult(raw)
138
+
129
139
  def get_layer(
130
140
  self,
131
141
  user: StatsigUser,
@@ -221,6 +221,7 @@ class StatsigBasePy:
221
221
  def _INTERNAL_get_experiment(self, user: StatsigUser, name: builtins.str, options: typing.Optional[ExperimentEvaluationOptions] = None) -> dict: ...
222
222
  def _INTERNAL_get_experiment_by_group_name(self, experiment_name: builtins.str, group_name: builtins.str) -> dict: ...
223
223
  def _INTERNAL_get_experiment_by_group_id_advanced(self, experiment_name: builtins.str, group_id: builtins.str) -> dict: ...
224
+ def _INTERNAL_get_experiment_groups(self, experiment_name: builtins.str) -> dict: ...
224
225
  def manually_log_experiment_exposure(self, user: StatsigUser, name: builtins.str) -> None: ...
225
226
  def _INTERNAL_get_layer(self, user: StatsigUser, name: builtins.str, options: typing.Optional[LayerEvaluationOptions] = None) -> dict: ...
226
227
  def _INTERNAL_log_layer_param_exposure(self, raw: LayerParamExposureData, param_name: builtins.str) -> None: ...
@@ -1,5 +1,5 @@
1
1
  import json
2
- from typing import Any, Callable, Optional
2
+ from typing import Any, Callable, List, Optional
3
3
 
4
4
 
5
5
  def _log_error(tag: str, message: str):
@@ -334,3 +334,55 @@ class Layer(BaseEvaluation):
334
334
  return
335
335
 
336
336
  self.__exposure_func(param_name)
337
+
338
+
339
+ class ExperimentGroup:
340
+ group_name: str
341
+ rule_id: str
342
+ id_type: str
343
+ return_value: dict
344
+
345
+ def __init__(self, raw: dict):
346
+ try:
347
+ data = raw or {}
348
+ self.group_name = data.get("group_name") or ""
349
+ self.rule_id = data.get("rule_id") or ""
350
+ self.id_type = data.get("id_type") or ""
351
+ self.return_value = data.get("return_value") or {}
352
+ except Exception as error:
353
+ self.group_name = ""
354
+ self.rule_id = ""
355
+ self.id_type = ""
356
+ self.return_value = {}
357
+ _log_error("ExperimentGroup", f"Failed to parse. {error}")
358
+
359
+ def to_dict(self) -> dict:
360
+ return {
361
+ "group_name": self.group_name,
362
+ "rule_id": self.rule_id,
363
+ "id_type": self.id_type,
364
+ "return_value": self.return_value,
365
+ }
366
+
367
+
368
+ class ExperimentGroupsResult:
369
+ is_experiment_active: Optional[bool]
370
+ groups: List[ExperimentGroup]
371
+
372
+ def __init__(self, raw: dict):
373
+ try:
374
+ data = raw or {}
375
+ self.is_experiment_active = data.get("is_experiment_active")
376
+ self.groups = [
377
+ ExperimentGroup(group) for group in data.get("groups") or []
378
+ ]
379
+ except Exception as error:
380
+ self.is_experiment_active = None
381
+ self.groups = []
382
+ _log_error("ExperimentGroupsResult", f"Failed to parse. {error}")
383
+
384
+ def to_dict(self) -> dict:
385
+ return {
386
+ "is_experiment_active": self.is_experiment_active,
387
+ "groups": [group.to_dict() for group in self.groups],
388
+ }
@@ -65,10 +65,7 @@ pub fn map_to_py_dict(py: Python, map: &HashMap<String, Value>) -> Py<PyAny> {
65
65
  pub fn py_list_to_list(py_list: &Bound<PyList>) -> PyResult<Vec<String>> {
66
66
  let mut converted_list = Vec::new();
67
67
  for value in py_list {
68
- match value.extract::<String>() {
69
- Ok(s) => converted_list.push(s),
70
- Err(e) => return Err(e),
71
- }
68
+ converted_list.push(value.extract::<String>()?);
72
69
  }
73
70
  Ok(converted_list)
74
71
  }
@@ -19,6 +19,7 @@ use crate::{
19
19
  use parking_lot::Mutex;
20
20
  use pyo3::{
21
21
  call::PyCallArgs,
22
+ exceptions::PyValueError,
22
23
  prelude::*,
23
24
  types::{PyDict, PyModule},
24
25
  };
@@ -341,6 +342,21 @@ impl StatsigBasePy {
341
342
  json_string_to_py_dict(py, &raw)
342
343
  }
343
344
 
345
+ #[pyo3(name="_INTERNAL_get_experiment_groups", signature = (experiment_name))]
346
+ pub fn _internal_get_experiment_groups(
347
+ &self,
348
+ experiment_name: &str,
349
+ py: Python,
350
+ ) -> PyResult<Py<PyDict>> {
351
+ let result = self.inner.get_experiment_groups(experiment_name);
352
+
353
+ let json = serde_json::to_string(&result).map_err(|e| {
354
+ PyValueError::new_err(format!("Failed to serialize experiment groups: {e}"))
355
+ })?;
356
+
357
+ json_string_to_py_dict(py, &json)
358
+ }
359
+
344
360
  #[pyo3(signature = (user, name))]
345
361
  pub fn manually_log_experiment_exposure(
346
362
  &self,
@@ -618,10 +634,11 @@ fn extract_event_metadata(metadata: Option<Bound<PyDict>>) -> Option<HashMap<Str
618
634
  metadata.map(|m| py_dict_to_json_value_map(&m))
619
635
  }
620
636
 
621
- // The group-targeting experiment getters only expose a JSON-string core
622
- // method (the camelCase ExperimentRaw shape), so parse it into a PyDict here
623
- // via Python's json module. The resulting keys (ruleID, idType, groupName,
624
- // value, details) match what the Python Experiment type reads.
637
+ // Parses a JSON string from the core into a PyDict via Python's json module.
638
+ // Used by the group-targeting getters (camelCase ExperimentRaw shape, whose
639
+ // keys ruleID/idType/groupName/value/details match what the Python Experiment
640
+ // type reads) and by get_experiment_groups (snake_case ExperimentGroupsResult
641
+ // shape read by the Python ExperimentGroupsResult type).
625
642
  fn json_string_to_py_dict(py: Python, json_str: &str) -> PyResult<Py<PyDict>> {
626
643
  let json_module = PyModule::import(py, "json")?;
627
644
  let parsed = json_module.call_method1("loads", (json_str,))?;
@@ -479,6 +479,8 @@ fn create_inner_statsig_options(
479
479
  use_third_party_ua_parser: opts.use_third_party_ua_parser,
480
480
  disable_disk_access: opts.disable_disk_access,
481
481
  experimental_flags: opts.experimental_flags,
482
+ // Not exposed via the Python binding yet; defaults to the core value.
483
+ dcs_delta_no_progress_threshold: None,
482
484
  }
483
485
  }
484
486
 
@@ -169,12 +169,8 @@ fn convert_py_lists_to_secondary_exposures(
169
169
  ) -> PyResult<Vec<SecondaryExposure>> {
170
170
  let mut exposures = Vec::new();
171
171
  for item in py_list {
172
- match item.extract::<Bound<PyDict>>() {
173
- Ok(e) => {
174
- exposures.push(convert_py_dict_to_secondary_exposure(&e)?);
175
- }
176
- Err(e) => return Err(e.into()),
177
- }
172
+ let e = item.extract::<Bound<PyDict>>()?;
173
+ exposures.push(convert_py_dict_to_secondary_exposure(&e)?);
178
174
  }
179
175
 
180
176
  Ok(exposures)
@@ -0,0 +1,89 @@
1
+ from statsig_python_core import (
2
+ ExperimentGroup,
3
+ ExperimentGroupsResult,
4
+ Statsig,
5
+ StatsigOptions,
6
+ )
7
+ from pytest_httpserver import HTTPServer
8
+ import json
9
+ from utils import get_test_data_resource
10
+ import pytest
11
+
12
+
13
+ @pytest.fixture
14
+ def statsig_setup(httpserver: HTTPServer):
15
+ dcs_content = get_test_data_resource("eval_proj_dcs.json")
16
+ json_data = json.loads(dcs_content)
17
+
18
+ httpserver.expect_request(
19
+ "/v2/download_config_specs/secret-key.json"
20
+ ).respond_with_json(json_data)
21
+
22
+ httpserver.expect_request("/v1/log_event").respond_with_json({"success": True})
23
+
24
+ options = StatsigOptions(
25
+ specs_url=httpserver.url_for("/v2/download_config_specs"),
26
+ log_event_url=httpserver.url_for("/v1/log_event"),
27
+ )
28
+ statsig = Statsig("secret-key", options)
29
+
30
+ statsig.initialize().wait()
31
+
32
+ yield statsig
33
+
34
+ # Teardown
35
+ statsig.shutdown().wait()
36
+
37
+
38
+ def test_get_experiment_groups(statsig_setup):
39
+ statsig = statsig_setup
40
+ result = statsig.get_experiment_groups("test_experiment_no_targeting")
41
+
42
+ assert result.is_experiment_active is True
43
+
44
+ groups_by_name = {group.group_name: group for group in result.groups}
45
+
46
+ # Only the experiment group rules are returned (the layerAssignment rule is excluded).
47
+ assert sorted(groups_by_name.keys()) == ["Control", "Test", "Test2"]
48
+ assert groups_by_name["Control"].return_value == {"value": "control"}
49
+ assert groups_by_name["Control"].rule_id == "54QJztEPRLXK7ZCvXeY9q4"
50
+ assert groups_by_name["Control"].id_type == "userID"
51
+ assert groups_by_name["Test"].return_value == {"value": "test_1"}
52
+ assert groups_by_name["Test2"].return_value == {"value": "test_2"}
53
+
54
+
55
+ def test_get_experiment_groups_returns_typed_result(statsig_setup):
56
+ statsig = statsig_setup
57
+ result = statsig.get_experiment_groups("test_experiment_no_targeting")
58
+
59
+ assert isinstance(result, ExperimentGroupsResult)
60
+ assert all(isinstance(group, ExperimentGroup) for group in result.groups)
61
+
62
+
63
+ def test_get_experiment_groups_returns_none_for_unknown_experiment(statsig_setup):
64
+ statsig = statsig_setup
65
+ result = statsig.get_experiment_groups("nonexistent_experiment")
66
+
67
+ assert result.is_experiment_active is None
68
+ assert result.groups == []
69
+
70
+
71
+ def test_get_experiment_groups_returns_none_for_dynamic_config(statsig_setup):
72
+ statsig = statsig_setup
73
+ # Dynamic configs are not experiments; is_experiment_active should be None.
74
+ result = statsig.get_experiment_groups("test_max_dynamic_config_size_again")
75
+
76
+ assert result.is_experiment_active is None
77
+ assert result.groups == []
78
+
79
+
80
+ def test_get_experiment_groups_returns_groups_for_inactive_experiment(statsig_setup):
81
+ statsig = statsig_setup
82
+ # test_switchback has isActive: false; groups are still returned along with the flag.
83
+ result = statsig.get_experiment_groups("test_switchback")
84
+
85
+ assert result.is_experiment_active is False
86
+
87
+ # Only the experiment group rules are returned (non-group rules are excluded).
88
+ group_names = sorted(group.group_name for group in result.groups)
89
+ assert group_names == ["Control", "Test"]
@@ -41,7 +41,7 @@ serde_json = { version = "1.0.143", features = [
41
41
  ] }
42
42
  serde_with = "3.4.0"
43
43
  sha2 = "0.10.8"
44
- sigstat-grpc = { path = "../statsig-grpc", version = "0.20.1-rc.2607140134", optional = true }
44
+ sigstat-grpc = { path = "../statsig-grpc", version = "0.20.2", optional = true }
45
45
  simple_logger = { version = "5.0.0" }
46
46
  tempfile = "3.8.1"
47
47
  tokio = { version = "1.39.1", features = ["full"] }
@@ -128,12 +128,12 @@ impl CountryLookup {
128
128
  return None;
129
129
  }
130
130
 
131
- let ip = match user.get_user_value(&Some(DynamicString::from(IP.to_string()))) {
132
- Some(v) => match &v.string_value {
131
+ let ip = {
132
+ let v = user.get_user_value(&Some(DynamicString::from(IP.to_string())))?;
133
+ match &v.string_value {
133
134
  Some(s) => &s.value,
134
135
  _ => return None,
135
- },
136
- None => return None,
136
+ }
137
137
  };
138
138
 
139
139
  Self::lookup(ip, evaluator_context)
@@ -70,6 +70,16 @@ fn os_name_parsing_macos_no_x() {
70
70
  assert_eq!(os_version, Some("26.2.0".to_string()));
71
71
  }
72
72
 
73
+ #[test]
74
+ fn os_name_parsing_ipados() {
75
+ let user_agent = "Whatnot v26.26.0 (42), iPadOS 26.5, iPad13,19";
76
+ let os = UaParser::parse_os(user_agent);
77
+
78
+ assert_eq!(os.name, "iOS");
79
+ let os_version = os.version.get_version_string();
80
+ assert_eq!(os_version, Some("26.5".to_string()));
81
+ }
82
+
73
83
  #[test]
74
84
  fn os_name_parsing_ubuntu() {
75
85
  let user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/604.1 (KHTML, like Gecko) Version/11.0 Safari/604.1 Ubuntu/17.04 (3.24.1-0ubuntu1) Epiphany/3.24.1"; // |Ubuntu|17|04|None|None|Epiphany|3|24|1|None
@@ -58,6 +58,12 @@ impl Tokenizer {
58
58
 
59
59
  win.slide_window_by(1);
60
60
  }
61
+ // iPadOS
62
+ else if curr == "iPadOS" {
63
+ result.add_possible_os_tag("iOS", consume_if_numeric(&mut win, next1));
64
+ result.ios_hint = true;
65
+ win.slide_window_by(1);
66
+ }
61
67
  // iPad
62
68
  else if curr.starts_with("iPad") {
63
69
  result.ios_hint = true;
@@ -42,12 +42,12 @@ impl UserAgentParser {
42
42
  _ => return None,
43
43
  };
44
44
 
45
- let user_agent = match user.get_user_value(&USER_AGENT_STRING) {
46
- Some(v) => match &v.string_value {
45
+ let user_agent = {
46
+ let v = user.get_user_value(&USER_AGENT_STRING)?;
47
+ match &v.string_value {
47
48
  Some(s) => &s.value,
48
49
  _ => return None,
49
- },
50
- None => return None,
50
+ }
51
51
  };
52
52
 
53
53
  if user_agent.len() > 1000 {
@@ -82,7 +82,7 @@ pub(crate) fn get_dynamic_config_evaluations(
82
82
  .get(config_name)
83
83
  .and_then(|c| c.target_app_ids.as_ref()),
84
84
  &context.app_id,
85
- &options.client_sdk_key,
85
+ options,
86
86
  ) {
87
87
  continue;
88
88
  }
@@ -161,7 +161,7 @@ pub(crate) fn get_dynamic_config_evaluations_v2(
161
161
  let target_app_ids = cmab_configs
162
162
  .get(config_name)
163
163
  .and_then(|c| c.target_app_ids.as_ref());
164
- if should_filter_config_for_app(target_app_ids, &context.app_id, &options.client_sdk_key) {
164
+ if should_filter_config_for_app(target_app_ids, &context.app_id, options) {
165
165
  continue;
166
166
  }
167
167
  context.reset_result();
@@ -261,7 +261,7 @@ pub(crate) fn get_dynamic_config_evaluations_init_v2(
261
261
  let target_app_ids = cmab_configs
262
262
  .get(config_name)
263
263
  .and_then(|c| c.target_app_ids.as_ref());
264
- if should_filter_config_for_app(target_app_ids, &context.app_id, &options.client_sdk_key) {
264
+ if should_filter_config_for_app(target_app_ids, &context.app_id, options) {
265
265
  continue;
266
266
  }
267
267
  context.reset_result();
@@ -7,6 +7,7 @@ use crate::{GCIRResponseFormat, HashAlgorithm};
7
7
  pub struct ClientInitResponseOptions {
8
8
  pub hash_algorithm: Option<HashAlgorithm>,
9
9
  pub client_sdk_key: Option<String>,
10
+ pub target_app_id: Option<String>,
10
11
  pub include_local_overrides: Option<bool>,
11
12
  pub feature_gate_filter: Option<HashSet<String>>,
12
13
  pub experiment_filter: Option<HashSet<String>>,
@@ -24,6 +25,13 @@ impl ClientInitResponseOptions {
24
25
  pub(crate) fn get_hash_algorithm(&self) -> &HashAlgorithm {
25
26
  self.hash_algorithm.as_ref().unwrap_or(&HashAlgorithm::Djb2)
26
27
  }
28
+
29
+ // Empty string means unset: bindings without nullable strings (e.g. Go) send "".
30
+ pub(crate) fn get_target_app_id(&self) -> Option<&String> {
31
+ self.target_app_id
32
+ .as_ref()
33
+ .filter(|target_app_id| !target_app_id.is_empty())
34
+ }
27
35
  }
28
36
 
29
37
  impl Default for ClientInitResponseOptions {
@@ -31,6 +39,7 @@ impl Default for ClientInitResponseOptions {
31
39
  Self {
32
40
  hash_algorithm: Some(HashAlgorithm::Djb2),
33
41
  client_sdk_key: None,
42
+ target_app_id: None,
34
43
  include_local_overrides: Some(false),
35
44
  feature_gate_filter: None,
36
45
  experiment_filter: None,
@@ -41,7 +41,7 @@ pub(crate) fn gcir_process_iter<T: GCIRHashable>(
41
41
  continue;
42
42
  }
43
43
 
44
- if should_filter_spec_for_app(spec, &context.app_id, &options.client_sdk_key) {
44
+ if should_filter_spec_for_app(spec, &context.app_id, options) {
45
45
  continue;
46
46
  }
47
47
 
@@ -34,11 +34,7 @@ pub(crate) fn get_serializeable_param_stores(
34
34
  let mut param_stores = HashMap::new();
35
35
 
36
36
  for (name, store) in stores {
37
- if should_filter_config_for_app(
38
- store.target_app_ids.as_ref(),
39
- &context.app_id,
40
- &options.client_sdk_key,
41
- ) {
37
+ if should_filter_config_for_app(store.target_app_ids.as_ref(), &context.app_id, options) {
42
38
  continue;
43
39
  }
44
40
 
@@ -5,16 +5,20 @@ use crate::{
5
5
  ClientInitResponseOptions, DynamicValue, HashAlgorithm,
6
6
  };
7
7
 
8
- pub(crate) fn select_app_id_for_gcir<'a>(
9
- options: &'a ClientInitResponseOptions,
10
- dcs_values: &'a SpecsResponseFull,
8
+ pub(crate) fn select_app_id_for_gcir(
9
+ options: &ClientInitResponseOptions,
10
+ dcs_values: &SpecsResponseFull,
11
11
  hashing: &HashUtil,
12
- ) -> Option<&'a DynamicValue> {
12
+ ) -> Option<DynamicValue> {
13
+ if let Some(target_app_id) = options.get_target_app_id() {
14
+ return Some(DynamicValue::from(target_app_id.clone()));
15
+ }
16
+
13
17
  let mut app_id = dcs_values.app_id.as_ref();
14
18
 
15
19
  let client_sdk_key = match options.client_sdk_key.as_ref() {
16
20
  Some(client_sdk_key) => client_sdk_key,
17
- None => return app_id,
21
+ None => return app_id.cloned(),
18
22
  };
19
23
 
20
24
  if let Some(app_id_value) = &dcs_values.sdk_keys_to_app_ids {
@@ -26,26 +30,25 @@ pub(crate) fn select_app_id_for_gcir<'a>(
26
30
  app_id = app_id_value.get(hashed_key);
27
31
  }
28
32
 
29
- app_id
33
+ app_id.cloned()
30
34
  }
31
35
 
32
36
  pub(crate) fn should_filter_spec_for_app(
33
37
  spec: &Spec,
34
38
  app_id: &Option<&DynamicValue>,
35
- client_sdk_key: &Option<String>,
39
+ options: &ClientInitResponseOptions,
36
40
  ) -> bool {
37
- should_filter_config_for_app(spec.target_app_ids.as_ref(), app_id, client_sdk_key)
41
+ should_filter_config_for_app(spec.target_app_ids.as_ref(), app_id, options)
38
42
  }
39
43
 
40
44
  pub(crate) fn should_filter_config_for_app(
41
45
  target_app_ids: Option<&Vec<InternedString>>,
42
46
  app_id: &Option<&DynamicValue>,
43
- client_sdk_key: &Option<String>,
47
+ options: &ClientInitResponseOptions,
44
48
  ) -> bool {
45
- let _client_sdk_key = match client_sdk_key {
46
- Some(client_sdk_key) => client_sdk_key,
47
- None => return false,
48
- };
49
+ if options.client_sdk_key.is_none() && options.get_target_app_id().is_none() {
50
+ return false;
51
+ }
49
52
 
50
53
  let app_id = match app_id {
51
54
  Some(app_id) => app_id,
@@ -58,9 +58,9 @@ impl InstanceRegistry {
58
58
  // does not outlive this statement) so we never hold a DashMap guard
59
59
  // across other registry calls - that is what could otherwise deadlock
60
60
  // a sharded map.
61
- let any_arc = match REGISTRY.get(id) {
62
- Some(entry) => entry.value().clone(),
63
- None => return None,
61
+ let any_arc = {
62
+ let entry = REGISTRY.get(id)?;
63
+ entry.value().clone()
64
64
  };
65
65
 
66
66
  match any_arc.downcast::<T>() {
@@ -6,7 +6,9 @@ pub use statsig_bootstrap_specs_adapter::StatsigBootstrapSpecsAdapter;
6
6
  pub use statsig_customized_specs_adapter::StatsigCustomizedSpecsAdapter;
7
7
  #[cfg(feature = "with_grpc")]
8
8
  pub use statsig_grpc_specs_adapter::StatsigGrpcSpecsAdapter;
9
- pub use statsig_http_specs_adapter::{SpecsSyncTrigger, StatsigHttpSpecsAdapter};
9
+ pub use statsig_http_specs_adapter::{
10
+ SpecsSyncTrigger, StatsigHttpSpecsAdapter, DEFAULT_DCS_DELTA_NO_PROGRESS_THRESHOLD,
11
+ };
10
12
  pub use statsig_local_file_specs_adapter::StatsigLocalFileSpecsAdapter;
11
13
 
12
14
  mod config_spec_background_sync_metrics;