sift-stack-py 0.17.0.dev0__tar.gz → 0.17.0.dev2__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 (582) hide show
  1. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/PKG-INFO +2 -1
  2. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/transport.py +5 -20
  3. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/_test_results_log.py +6 -2
  4. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/test_results.py +11 -3
  5. sift_stack_py-0.17.0.dev2/lib/sift_client/_internal/pyproject_config.py +84 -0
  6. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/rest.py +2 -2
  7. sift_stack_py-0.17.0.dev2/lib/sift_client/_internal/urls.py +55 -0
  8. sift_stack_py-0.17.0.dev2/lib/sift_client/_internal/util/hdf5.py +271 -0
  9. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/client.py +27 -0
  10. sift_stack_py-0.17.0.dev2/lib/sift_client/pytest_plugin.py +1898 -0
  11. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/data_imports.py +87 -14
  12. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/sync_stubs/__init__.pyi +29 -10
  13. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/test_results.py +2 -1
  14. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/scripts/import_test_result_log.py +2 -1
  15. sift_stack_py-0.17.0.dev2/lib/sift_client/sift_types/_mixins/metadata.py +19 -0
  16. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/asset.py +2 -0
  17. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/data_import.py +54 -16
  18. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/report.py +2 -0
  19. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/run.py +2 -0
  20. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/test_report.py +38 -0
  21. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/transport/base_connection.py +6 -0
  22. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/test_results/context_manager.py +72 -6
  23. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_stack_py.egg-info/PKG-INFO +2 -1
  24. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_stack_py.egg-info/SOURCES.txt +3 -0
  25. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_stack_py.egg-info/requires.txt +3 -0
  26. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/pyproject.toml +2 -1
  27. sift_stack_py-0.17.0.dev0/lib/sift_client/_internal/util/hdf5.py +0 -96
  28. sift_stack_py-0.17.0.dev0/lib/sift_client/pytest_plugin.py +0 -1086
  29. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/LICENSE +0 -0
  30. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/README.md +0 -0
  31. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/__init__.py +0 -0
  32. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotation_logs/__init__.py +0 -0
  33. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotation_logs/v1/__init__.py +0 -0
  34. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotation_logs/v1/annotation_logs_pb2.py +0 -0
  35. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotation_logs/v1/annotation_logs_pb2.pyi +0 -0
  36. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotation_logs/v1/annotation_logs_pb2_grpc.py +0 -0
  37. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotation_logs/v1/annotation_logs_pb2_grpc.pyi +0 -0
  38. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotations/__init__.py +0 -0
  39. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotations/v1/__init__.py +0 -0
  40. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotations/v1/annotations_pb2.py +0 -0
  41. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotations/v1/annotations_pb2.pyi +0 -0
  42. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotations/v1/annotations_pb2_grpc.py +0 -0
  43. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/annotations/v1/annotations_pb2_grpc.pyi +0 -0
  44. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/api_keys/__init__.py +0 -0
  45. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/api_keys/v2/__init__.py +0 -0
  46. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/api_keys/v2/api_keys_pb2.py +0 -0
  47. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/api_keys/v2/api_keys_pb2.pyi +0 -0
  48. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/api_keys/v2/api_keys_pb2_grpc.py +0 -0
  49. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/api_keys/v2/api_keys_pb2_grpc.pyi +0 -0
  50. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/assets/__init__.py +0 -0
  51. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/assets/v1/__init__.py +0 -0
  52. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/assets/v1/assets_pb2.py +0 -0
  53. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/assets/v1/assets_pb2.pyi +0 -0
  54. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/assets/v1/assets_pb2_grpc.py +0 -0
  55. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/assets/v1/assets_pb2_grpc.pyi +0 -0
  56. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/__init__.py +0 -0
  57. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v1/__init__.py +0 -0
  58. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v1/calculated_channels_pb2.py +0 -0
  59. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v1/calculated_channels_pb2.pyi +0 -0
  60. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v1/calculated_channels_pb2_grpc.py +0 -0
  61. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v1/calculated_channels_pb2_grpc.pyi +0 -0
  62. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v2/__init__.py +0 -0
  63. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v2/calculated_channels_pb2.py +0 -0
  64. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v2/calculated_channels_pb2.pyi +0 -0
  65. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v2/calculated_channels_pb2_grpc.py +0 -0
  66. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/calculated_channels/v2/calculated_channels_pb2_grpc.pyi +0 -0
  67. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/campaigns/__init__.py +0 -0
  68. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/campaigns/v1/__init__.py +0 -0
  69. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/campaigns/v1/campaigns_pb2.py +0 -0
  70. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/campaigns/v1/campaigns_pb2.pyi +0 -0
  71. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/campaigns/v1/campaigns_pb2_grpc.py +0 -0
  72. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/campaigns/v1/campaigns_pb2_grpc.pyi +0 -0
  73. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/__init__.py +0 -0
  74. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v1/__init__.py +0 -0
  75. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v1/channel_schemas_pb2.py +0 -0
  76. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v1/channel_schemas_pb2.pyi +0 -0
  77. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v1/channel_schemas_pb2_grpc.py +0 -0
  78. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v1/channel_schemas_pb2_grpc.pyi +0 -0
  79. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v2/__init__.py +0 -0
  80. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v2/channel_schemas_pb2.py +0 -0
  81. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v2/channel_schemas_pb2.pyi +0 -0
  82. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v2/channel_schemas_pb2_grpc.py +0 -0
  83. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channel_schemas/v2/channel_schemas_pb2_grpc.pyi +0 -0
  84. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/__init__.py +0 -0
  85. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v2/__init__.py +0 -0
  86. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v2/channels_pb2.py +0 -0
  87. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v2/channels_pb2.pyi +0 -0
  88. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v2/channels_pb2_grpc.py +0 -0
  89. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v2/channels_pb2_grpc.pyi +0 -0
  90. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v3/__init__.py +0 -0
  91. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v3/channels_pb2.py +0 -0
  92. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v3/channels_pb2.pyi +0 -0
  93. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v3/channels_pb2_grpc.py +0 -0
  94. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/channels/v3/channels_pb2_grpc.pyi +0 -0
  95. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/comment/__init__.py +0 -0
  96. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/comment/v1/__init__.py +0 -0
  97. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/comment/v1/comment_pb2.py +0 -0
  98. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/comment/v1/comment_pb2.pyi +0 -0
  99. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/comment/v1/comment_pb2_grpc.py +0 -0
  100. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/comment/v1/comment_pb2_grpc.pyi +0 -0
  101. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/__init__.py +0 -0
  102. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/__init__.py +0 -0
  103. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/__init__.py +0 -0
  104. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/calculated_channels_pb2.py +0 -0
  105. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/calculated_channels_pb2.pyi +0 -0
  106. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/calculated_channels_pb2_grpc.py +0 -0
  107. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/calculated_channels_pb2_grpc.pyi +0 -0
  108. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_bit_field_element_pb2.py +0 -0
  109. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_bit_field_element_pb2.pyi +0 -0
  110. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_bit_field_element_pb2_grpc.py +0 -0
  111. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_bit_field_element_pb2_grpc.pyi +0 -0
  112. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_config_pb2.py +0 -0
  113. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_config_pb2.pyi +0 -0
  114. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_config_pb2_grpc.py +0 -0
  115. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_config_pb2_grpc.pyi +0 -0
  116. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_data_type_pb2.py +0 -0
  117. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_data_type_pb2.pyi +0 -0
  118. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_data_type_pb2_grpc.py +0 -0
  119. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_data_type_pb2_grpc.pyi +0 -0
  120. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_enum_type_pb2.py +0 -0
  121. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_enum_type_pb2.pyi +0 -0
  122. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_enum_type_pb2_grpc.py +0 -0
  123. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/channel_enum_type_pb2_grpc.pyi +0 -0
  124. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/organization_pb2.py +0 -0
  125. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/organization_pb2.pyi +0 -0
  126. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/organization_pb2_grpc.py +0 -0
  127. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/organization_pb2_grpc.pyi +0 -0
  128. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_identifier_pb2.py +0 -0
  129. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_identifier_pb2.pyi +0 -0
  130. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_identifier_pb2_grpc.py +0 -0
  131. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_identifier_pb2_grpc.pyi +0 -0
  132. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_ref_pb2.py +0 -0
  133. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_ref_pb2.pyi +0 -0
  134. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_ref_pb2_grpc.py +0 -0
  135. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/resource_ref_pb2_grpc.pyi +0 -0
  136. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_defined_functions_pb2.py +0 -0
  137. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_defined_functions_pb2.pyi +0 -0
  138. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_defined_functions_pb2_grpc.py +0 -0
  139. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_defined_functions_pb2_grpc.pyi +0 -0
  140. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_pb2.py +0 -0
  141. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_pb2.pyi +0 -0
  142. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_pb2_grpc.py +0 -0
  143. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/type/v1/user_pb2_grpc.pyi +0 -0
  144. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/__init__.py +0 -0
  145. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/action_type_pb2.py +0 -0
  146. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/action_type_pb2.pyi +0 -0
  147. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/action_type_pb2_grpc.py +0 -0
  148. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/action_type_pb2_grpc.pyi +0 -0
  149. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/filter_field_pb2.py +0 -0
  150. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/filter_field_pb2.pyi +0 -0
  151. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/filter_field_pb2_grpc.py +0 -0
  152. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/filter_field_pb2_grpc.pyi +0 -0
  153. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/resource_type_pb2.py +0 -0
  154. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/resource_type_pb2.pyi +0 -0
  155. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/resource_type_pb2_grpc.py +0 -0
  156. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/common/v1/resource_type_pb2_grpc.pyi +0 -0
  157. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/__init__.py +0 -0
  158. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v1/__init__.py +0 -0
  159. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v1/data_pb2.py +0 -0
  160. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v1/data_pb2.pyi +0 -0
  161. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v1/data_pb2_grpc.py +0 -0
  162. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v1/data_pb2_grpc.pyi +0 -0
  163. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v2/__init__.py +0 -0
  164. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v2/data_pb2.py +0 -0
  165. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v2/data_pb2.pyi +0 -0
  166. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v2/data_pb2_grpc.py +0 -0
  167. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data/v2/data_pb2_grpc.pyi +0 -0
  168. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data_imports/__init__.py +0 -0
  169. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data_imports/v2/__init__.py +0 -0
  170. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data_imports/v2/data_imports_pb2.py +0 -0
  171. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data_imports/v2/data_imports_pb2.pyi +0 -0
  172. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data_imports/v2/data_imports_pb2_grpc.py +0 -0
  173. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/data_imports/v2/data_imports_pb2_grpc.pyi +0 -0
  174. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/dlq_errors/__init__.py +0 -0
  175. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/dlq_errors/v2/__init__.py +0 -0
  176. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/dlq_errors/v2/dlq_errors_pb2.py +0 -0
  177. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/dlq_errors/v2/dlq_errors_pb2.pyi +0 -0
  178. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/dlq_errors/v2/dlq_errors_pb2_grpc.py +0 -0
  179. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/dlq_errors/v2/dlq_errors_pb2_grpc.pyi +0 -0
  180. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/exports/__init__.py +0 -0
  181. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/exports/v1/__init__.py +0 -0
  182. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/exports/v1/exports_pb2.py +0 -0
  183. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/exports/v1/exports_pb2.pyi +0 -0
  184. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/exports/v1/exports_pb2_grpc.py +0 -0
  185. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/exports/v1/exports_pb2_grpc.pyi +0 -0
  186. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/external_sync/__init__.py +0 -0
  187. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/external_sync/v1/__init__.py +0 -0
  188. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/external_sync/v1/external_sync_pb2.py +0 -0
  189. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/external_sync/v1/external_sync_pb2.pyi +0 -0
  190. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/external_sync/v1/external_sync_pb2_grpc.py +0 -0
  191. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/external_sync/v1/external_sync_pb2_grpc.pyi +0 -0
  192. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingest/__init__.py +0 -0
  193. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingest/v1/__init__.py +0 -0
  194. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingest/v1/ingest_pb2.py +0 -0
  195. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingest/v1/ingest_pb2.pyi +0 -0
  196. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingest/v1/ingest_pb2_grpc.py +0 -0
  197. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingest/v1/ingest_pb2_grpc.pyi +0 -0
  198. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/__init__.py +0 -0
  199. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v1/__init__.py +0 -0
  200. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v1/ingestion_configs_pb2.py +0 -0
  201. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v1/ingestion_configs_pb2.pyi +0 -0
  202. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v1/ingestion_configs_pb2_grpc.py +0 -0
  203. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v1/ingestion_configs_pb2_grpc.pyi +0 -0
  204. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v2/__init__.py +0 -0
  205. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v2/ingestion_configs_pb2.py +0 -0
  206. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v2/ingestion_configs_pb2.pyi +0 -0
  207. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v2/ingestion_configs_pb2_grpc.py +0 -0
  208. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ingestion_configs/v2/ingestion_configs_pb2_grpc.pyi +0 -0
  209. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/jobs/__init__.py +0 -0
  210. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/jobs/v1/__init__.py +0 -0
  211. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/jobs/v1/jobs_pb2.py +0 -0
  212. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/jobs/v1/jobs_pb2.pyi +0 -0
  213. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/jobs/v1/jobs_pb2_grpc.py +0 -0
  214. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/jobs/v1/jobs_pb2_grpc.pyi +0 -0
  215. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/me/__init__.py +0 -0
  216. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/me/v2/__init__.py +0 -0
  217. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/me/v2/me_pb2.py +0 -0
  218. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/me/v2/me_pb2.pyi +0 -0
  219. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/me/v2/me_pb2_grpc.py +0 -0
  220. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/me/v2/me_pb2_grpc.pyi +0 -0
  221. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/metadata/__init__.py +0 -0
  222. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/metadata/v1/__init__.py +0 -0
  223. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/metadata/v1/metadata_pb2.py +0 -0
  224. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/metadata/v1/metadata_pb2.pyi +0 -0
  225. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/metadata/v1/metadata_pb2_grpc.py +0 -0
  226. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/metadata/v1/metadata_pb2_grpc.pyi +0 -0
  227. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/notifications/__init__.py +0 -0
  228. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/notifications/v1/__init__.py +0 -0
  229. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/notifications/v1/notifications_pb2.py +0 -0
  230. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/notifications/v1/notifications_pb2.pyi +0 -0
  231. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/notifications/v1/notifications_pb2_grpc.py +0 -0
  232. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/notifications/v1/notifications_pb2_grpc.pyi +0 -0
  233. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/panel_configurations/__init__.py +0 -0
  234. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/panel_configurations/v1/__init__.py +0 -0
  235. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/panel_configurations/v1/panel_configuration_pb2.py +0 -0
  236. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/panel_configurations/v1/panel_configuration_pb2.pyi +0 -0
  237. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/panel_configurations/v1/panel_configuration_pb2_grpc.py +0 -0
  238. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/panel_configurations/v1/panel_configuration_pb2_grpc.pyi +0 -0
  239. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ping/__init__.py +0 -0
  240. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ping/v1/__init__.py +0 -0
  241. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ping/v1/ping_pb2.py +0 -0
  242. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ping/v1/ping_pb2.pyi +0 -0
  243. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ping/v1/ping_pb2_grpc.py +0 -0
  244. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/ping/v1/ping_pb2_grpc.pyi +0 -0
  245. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/__init__.py +0 -0
  246. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/__init__.py +0 -0
  247. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/channel_parsing_options_pb2.py +0 -0
  248. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/channel_parsing_options_pb2.pyi +0 -0
  249. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/channel_parsing_options_pb2_grpc.py +0 -0
  250. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/channel_parsing_options_pb2_grpc.pyi +0 -0
  251. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/protobuf_descriptors_pb2.py +0 -0
  252. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/protobuf_descriptors_pb2.pyi +0 -0
  253. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/protobuf_descriptors_pb2_grpc.py +0 -0
  254. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/protobuf_descriptors/v2/protobuf_descriptors_pb2_grpc.pyi +0 -0
  255. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/py.typed +0 -0
  256. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/remote_files/__init__.py +0 -0
  257. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/remote_files/v1/__init__.py +0 -0
  258. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/remote_files/v1/remote_files_pb2.py +0 -0
  259. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/remote_files/v1/remote_files_pb2.pyi +0 -0
  260. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/remote_files/v1/remote_files_pb2_grpc.py +0 -0
  261. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/remote_files/v1/remote_files_pb2_grpc.pyi +0 -0
  262. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/report_templates/__init__.py +0 -0
  263. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/report_templates/v1/__init__.py +0 -0
  264. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/report_templates/v1/report_templates_pb2.py +0 -0
  265. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/report_templates/v1/report_templates_pb2.pyi +0 -0
  266. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/report_templates/v1/report_templates_pb2_grpc.py +0 -0
  267. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/report_templates/v1/report_templates_pb2_grpc.pyi +0 -0
  268. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/reports/__init__.py +0 -0
  269. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/reports/v1/__init__.py +0 -0
  270. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/reports/v1/reports_pb2.py +0 -0
  271. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/reports/v1/reports_pb2.pyi +0 -0
  272. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/reports/v1/reports_pb2_grpc.py +0 -0
  273. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/reports/v1/reports_pb2_grpc.pyi +0 -0
  274. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/roles/__init__.py +0 -0
  275. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/roles/v2/__init__.py +0 -0
  276. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/roles/v2/roles_pb2.py +0 -0
  277. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/roles/v2/roles_pb2.pyi +0 -0
  278. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/roles/v2/roles_pb2_grpc.py +0 -0
  279. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/roles/v2/roles_pb2_grpc.pyi +0 -0
  280. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rule_evaluation/__init__.py +0 -0
  281. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rule_evaluation/v1/__init__.py +0 -0
  282. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.py +0 -0
  283. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.pyi +0 -0
  284. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rule_evaluation/v1/rule_evaluation_pb2_grpc.py +0 -0
  285. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rule_evaluation/v1/rule_evaluation_pb2_grpc.pyi +0 -0
  286. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rules/__init__.py +0 -0
  287. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rules/v1/__init__.py +0 -0
  288. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rules/v1/rules_pb2.py +0 -0
  289. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rules/v1/rules_pb2.pyi +0 -0
  290. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rules/v1/rules_pb2_grpc.py +0 -0
  291. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/rules/v1/rules_pb2_grpc.pyi +0 -0
  292. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/runs/__init__.py +0 -0
  293. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/runs/v2/__init__.py +0 -0
  294. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/runs/v2/runs_pb2.py +0 -0
  295. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/runs/v2/runs_pb2.pyi +0 -0
  296. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/runs/v2/runs_pb2_grpc.py +0 -0
  297. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/runs/v2/runs_pb2_grpc.pyi +0 -0
  298. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/saved_searches/__init__.py +0 -0
  299. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/saved_searches/v1/__init__.py +0 -0
  300. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/saved_searches/v1/saved_searches_pb2.py +0 -0
  301. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/saved_searches/v1/saved_searches_pb2.pyi +0 -0
  302. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/saved_searches/v1/saved_searches_pb2_grpc.py +0 -0
  303. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/saved_searches/v1/saved_searches_pb2_grpc.pyi +0 -0
  304. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/__init__.py +0 -0
  305. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v1/__init__.py +0 -0
  306. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v1/tags_pb2.py +0 -0
  307. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v1/tags_pb2.pyi +0 -0
  308. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v1/tags_pb2_grpc.py +0 -0
  309. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v1/tags_pb2_grpc.pyi +0 -0
  310. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v2/__init__.py +0 -0
  311. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v2/tags_pb2.py +0 -0
  312. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v2/tags_pb2.pyi +0 -0
  313. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v2/tags_pb2_grpc.py +0 -0
  314. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/tags/v2/tags_pb2_grpc.pyi +0 -0
  315. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/test_reports/__init__.py +0 -0
  316. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/test_reports/v1/__init__.py +0 -0
  317. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/test_reports/v1/test_reports_pb2.py +0 -0
  318. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/test_reports/v1/test_reports_pb2.pyi +0 -0
  319. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/test_reports/v1/test_reports_pb2_grpc.py +0 -0
  320. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/test_reports/v1/test_reports_pb2_grpc.pyi +0 -0
  321. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/unit/__init__.py +0 -0
  322. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/unit/v2/__init__.py +0 -0
  323. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/unit/v2/unit_pb2.py +0 -0
  324. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/unit/v2/unit_pb2.pyi +0 -0
  325. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/unit/v2/unit_pb2_grpc.py +0 -0
  326. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/unit/v2/unit_pb2_grpc.pyi +0 -0
  327. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_defined_functions/__init__.py +0 -0
  328. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_defined_functions/v1/__init__.py +0 -0
  329. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_defined_functions/v1/user_defined_functions_pb2.py +0 -0
  330. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_defined_functions/v1/user_defined_functions_pb2.pyi +0 -0
  331. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_defined_functions/v1/user_defined_functions_pb2_grpc.py +0 -0
  332. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_defined_functions/v1/user_defined_functions_pb2_grpc.pyi +0 -0
  333. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_groups/__init__.py +0 -0
  334. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_groups/v2/__init__.py +0 -0
  335. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_groups/v2/user_groups_pb2.py +0 -0
  336. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_groups/v2/user_groups_pb2.pyi +0 -0
  337. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_groups/v2/user_groups_pb2_grpc.py +0 -0
  338. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/user_groups/v2/user_groups_pb2_grpc.pyi +0 -0
  339. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/users/__init__.py +0 -0
  340. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/users/v2/__init__.py +0 -0
  341. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/users/v2/users_pb2.py +0 -0
  342. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/users/v2/users_pb2.pyi +0 -0
  343. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/users/v2/users_pb2_grpc.py +0 -0
  344. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/users/v2/users_pb2_grpc.pyi +0 -0
  345. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/__init__.py +0 -0
  346. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v1/__init__.py +0 -0
  347. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v1/views_pb2.py +0 -0
  348. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v1/views_pb2.pyi +0 -0
  349. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v1/views_pb2_grpc.py +0 -0
  350. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v1/views_pb2_grpc.pyi +0 -0
  351. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v2/__init__.py +0 -0
  352. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v2/views_pb2.py +0 -0
  353. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v2/views_pb2.pyi +0 -0
  354. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v2/views_pb2_grpc.py +0 -0
  355. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/views/v2/views_pb2_grpc.pyi +0 -0
  356. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/webhooks/__init__.py +0 -0
  357. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/webhooks/v1/__init__.py +0 -0
  358. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/webhooks/v1/webhooks_pb2.py +0 -0
  359. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/webhooks/v1/webhooks_pb2.pyi +0 -0
  360. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/webhooks/v1/webhooks_pb2_grpc.py +0 -0
  361. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift/webhooks/v1/webhooks_pb2_grpc.pyi +0 -0
  362. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/__init__.py +0 -0
  363. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/__init__.py +0 -0
  364. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/gen_pyi.py +0 -0
  365. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/__init__.py +0 -0
  366. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_async_interceptors/__init__.py +0 -0
  367. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_async_interceptors/base.py +0 -0
  368. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_async_interceptors/metadata.py +0 -0
  369. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_interceptors/__init__.py +0 -0
  370. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_interceptors/base.py +0 -0
  371. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_interceptors/context.py +0 -0
  372. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_interceptors/metadata.py +0 -0
  373. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/_retry.py +0 -0
  374. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/keepalive.py +0 -0
  375. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/server_interceptors/__init__.py +0 -0
  376. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/server_interceptors/server_interceptor.py +0 -0
  377. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/grpc_transport/transport_test.py +0 -0
  378. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/__init__.py +0 -0
  379. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/assets.py +0 -0
  380. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/base.py +0 -0
  381. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/calculated_channels.py +0 -0
  382. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/channels.py +0 -0
  383. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/data.py +0 -0
  384. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/data_imports.py +0 -0
  385. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/exports.py +0 -0
  386. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/ingestion.py +0 -0
  387. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/jobs.py +0 -0
  388. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/ping.py +0 -0
  389. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/remote_files.py +0 -0
  390. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/reports.py +0 -0
  391. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/rules.py +0 -0
  392. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/runs.py +0 -0
  393. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/tags.py +0 -0
  394. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/low_level_wrappers/upload.py +0 -0
  395. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/sync_wrapper.py +0 -0
  396. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/time.py +0 -0
  397. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/__init__.py +0 -0
  398. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/channels.py +0 -0
  399. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/executor.py +0 -0
  400. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/file.py +0 -0
  401. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/numpy_types.py +0 -0
  402. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/tdms.py +0 -0
  403. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/timestamp.py +0 -0
  404. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/_internal/util/util.py +0 -0
  405. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/config.py +0 -0
  406. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/errors.py +0 -0
  407. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/py.typed +0 -0
  408. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/__init__.py +0 -0
  409. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/_base.py +0 -0
  410. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/assets.py +0 -0
  411. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/calculated_channels.py +0 -0
  412. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/channels.py +0 -0
  413. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/exports.py +0 -0
  414. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/file_attachments.py +0 -0
  415. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/ingestion.py +0 -0
  416. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/jobs.py +0 -0
  417. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/ping.py +0 -0
  418. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/py.typed +0 -0
  419. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/reports.py +0 -0
  420. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/rules.py +0 -0
  421. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/runs.py +0 -0
  422. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/sync_stubs/__init__.py +0 -0
  423. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/sync_stubs/py.typed +0 -0
  424. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/resources/tags.py +0 -0
  425. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/scripts/__init__.py +0 -0
  426. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/__init__.py +0 -0
  427. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/_base.py +0 -0
  428. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/_mixins/__init__.py +0 -0
  429. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/_mixins/file_attachments.py +0 -0
  430. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/_mixins/simulated.py +0 -0
  431. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/calculated_channel.py +0 -0
  432. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/channel.py +0 -0
  433. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/export.py +0 -0
  434. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/file_attachment.py +0 -0
  435. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/ingestion.py +0 -0
  436. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/job.py +0 -0
  437. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/rule.py +0 -0
  438. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/sift_types/tag.py +0 -0
  439. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/transport/__init__.py +0 -0
  440. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/transport/grpc_transport.py +0 -0
  441. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/transport/rest_transport.py +0 -0
  442. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/__init__.py +0 -0
  443. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/cel_utils.py +0 -0
  444. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/metadata.py +0 -0
  445. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/test_results/__init__.py +0 -0
  446. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/test_results/bounds.py +0 -0
  447. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_client/util/util.py +0 -0
  448. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/__init__.py +0 -0
  449. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/__init__.py +0 -0
  450. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/cel.py +0 -0
  451. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/channel.py +0 -0
  452. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/convert/__init__.py +0 -0
  453. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/convert/json.py +0 -0
  454. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/convert/protobuf.py +0 -0
  455. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/convert/timestamp.py +0 -0
  456. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/metadata.py +0 -0
  457. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/metadata_test.py +0 -0
  458. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/test_util/__init__.py +0 -0
  459. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/test_util/channel.py +0 -0
  460. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/test_util/fn.py +0 -0
  461. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/test_util/server_interceptor.py +0 -0
  462. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/time.py +0 -0
  463. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_internal/user.py +0 -0
  464. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/_rest_test.py +0 -0
  465. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/asset/__init__.py +0 -0
  466. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/asset/_config_test.py +0 -0
  467. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/asset/_internal/shared.py +0 -0
  468. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/asset/_service_test.py +0 -0
  469. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/asset/config.py +0 -0
  470. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/asset/service.py +0 -0
  471. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/calculated_channels/__init__.py +0 -0
  472. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/calculated_channels/_service_test.py +0 -0
  473. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/calculated_channels/config.py +0 -0
  474. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/calculated_channels/service.py +0 -0
  475. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/__init__.py +0 -0
  476. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/_channel.py +0 -0
  477. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/_deserialize.py +0 -0
  478. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/_deserialize_test.py +0 -0
  479. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/_service_test.py +0 -0
  480. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/_validate.py +0 -0
  481. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/error.py +0 -0
  482. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/query.py +0 -0
  483. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data/service.py +0 -0
  484. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/__init__.py +0 -0
  485. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_config.py +0 -0
  486. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_config_test.py +0 -0
  487. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_csv_test.py +0 -0
  488. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_hdf5_test.py +0 -0
  489. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_parquet_test.py +0 -0
  490. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_ros_channel.py +0 -0
  491. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_rosbag_test.py +0 -0
  492. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_status_test.py +0 -0
  493. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_tdms_test.py +0 -0
  494. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_utils.py +0 -0
  495. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/_utils_test.py +0 -0
  496. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/ch10.py +0 -0
  497. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/config.py +0 -0
  498. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/csv.py +0 -0
  499. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/hdf5.py +0 -0
  500. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/parquet.py +0 -0
  501. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/parquet_complex_types.py +0 -0
  502. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/rosbags.py +0 -0
  503. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/status.py +0 -0
  504. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/tdms.py +0 -0
  505. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/tempfile.py +0 -0
  506. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/data_import/time_format.py +0 -0
  507. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/error.py +0 -0
  508. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/__init__.py +0 -0
  509. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/_internal/__init__.py +0 -0
  510. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/_internal/download.py +0 -0
  511. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/_internal/upload.py +0 -0
  512. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/_service_test.py +0 -0
  513. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/entity.py +0 -0
  514. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/metadata.py +0 -0
  515. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/file_attachment/service.py +0 -0
  516. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/__init__.py +0 -0
  517. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_async_interceptors/__init__.py +0 -0
  518. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_async_interceptors/base.py +0 -0
  519. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_async_interceptors/metadata.py +0 -0
  520. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_interceptors/__init__.py +0 -0
  521. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_interceptors/base.py +0 -0
  522. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_interceptors/context.py +0 -0
  523. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_interceptors/metadata.py +0 -0
  524. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/_retry.py +0 -0
  525. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/keepalive.py +0 -0
  526. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/transport.py +0 -0
  527. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/grpc/transport_test.py +0 -0
  528. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/__init__.py +0 -0
  529. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/__init__.py +0 -0
  530. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/channel.py +0 -0
  531. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/error.py +0 -0
  532. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/ingest.py +0 -0
  533. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/ingest_test.py +0 -0
  534. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/ingestion_config.py +0 -0
  535. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_internal/run.py +0 -0
  536. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/_service_test.py +0 -0
  537. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/buffer.py +0 -0
  538. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/channel.py +0 -0
  539. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/__init__.py +0 -0
  540. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/_telemetry_test.py +0 -0
  541. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/telemetry.py +0 -0
  542. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/yaml/__init__.py +0 -0
  543. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/yaml/error.py +0 -0
  544. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/yaml/load.py +0 -0
  545. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/yaml/spec.py +0 -0
  546. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/config/yaml/test_load.py +0 -0
  547. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/flow.py +0 -0
  548. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/manager.py +0 -0
  549. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/rule/__init__.py +0 -0
  550. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/rule/config.py +0 -0
  551. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/ingestion/service.py +0 -0
  552. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/py.typed +0 -0
  553. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report/_report_test.py +0 -0
  554. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report/service.py +0 -0
  555. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report_templates/__init__.py +0 -0
  556. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report_templates/_config_test.py +0 -0
  557. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report_templates/_service_test.py +0 -0
  558. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report_templates/config.py +0 -0
  559. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/report_templates/service.py +0 -0
  560. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rest.py +0 -0
  561. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule/__init__.py +0 -0
  562. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule/_config_test.py +0 -0
  563. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule/_service_test.py +0 -0
  564. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule/config.py +0 -0
  565. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule/service.py +0 -0
  566. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule_evaluation/_service_test.py +0 -0
  567. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/rule_evaluation/service.py +0 -0
  568. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/tag/_internal/shared.py +0 -0
  569. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/__init__.py +0 -0
  570. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/_channel_test.py +0 -0
  571. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/_rule_test.py +0 -0
  572. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/_utils_test.py +0 -0
  573. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/calculated_channels.py +0 -0
  574. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/channel.py +0 -0
  575. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/report_templates.py +0 -0
  576. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/rule.py +0 -0
  577. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_py/yaml/utils.py +0 -0
  578. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_stack_py.egg-info/dependency_links.txt +0 -0
  579. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_stack_py.egg-info/entry_points.txt +0 -0
  580. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/lib/sift_stack_py.egg-info/top_level.txt +0 -0
  581. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/setup.cfg +0 -0
  582. {sift_stack_py-0.17.0.dev0 → sift_stack_py-0.17.0.dev2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sift_stack_py
3
- Version: 0.17.0.dev0
3
+ Version: 0.17.0.dev2
4
4
  Summary: Python client library for the Sift API
5
5
  Maintainer-email: Sift Software Engineers <engineering@siftstack.com>
6
6
  License: Copyright (c) 2024 Azimuth Industries Inc.
@@ -46,6 +46,7 @@ Requires-Dist: types-requests~=2.25
46
46
  Requires-Dist: googleapis-common-protos>=1.60
47
47
  Requires-Dist: protoc-gen-openapiv2>=0.0.1
48
48
  Requires-Dist: filelock~=3.13
49
+ Requires-Dist: tomli~=2.0; python_version < "3.11"
49
50
  Provides-Extra: all
50
51
  Requires-Dist: cffi~=1.14; extra == "all"
51
52
  Requires-Dist: h5py~=3.11; extra == "all"
@@ -8,7 +8,6 @@ from __future__ import annotations
8
8
 
9
9
  from importlib.metadata import PackageNotFoundError, version
10
10
  from typing import TYPE_CHECKING, Any, TypedDict, cast
11
- from urllib.parse import ParseResult, urlparse
12
11
 
13
12
  import grpc
14
13
  import grpc.aio as grpc_aio
@@ -21,6 +20,7 @@ from sift_client._internal.grpc_transport._interceptors.metadata import (
21
20
  Metadata,
22
21
  MetadataInterceptor,
23
22
  )
23
+ from sift_client._internal.urls import parse_host
24
24
 
25
25
  if TYPE_CHECKING:
26
26
  from sift_client._internal.grpc_transport._async_interceptors.base import ClientAsyncInterceptor
@@ -78,7 +78,7 @@ def use_sift_channel(
78
78
 
79
79
  credentials = get_ssl_credentials(cert_via_openssl)
80
80
  options = _compute_channel_options(config)
81
- api_uri = _clean_uri(config["uri"], use_ssl)
81
+ api_uri = parse_host(config["uri"])
82
82
  channel = grpc.secure_channel(api_uri, credentials, options)
83
83
  interceptors = _compute_sift_interceptors(config, metadata)
84
84
  return grpc.intercept_channel(channel, *interceptors)
@@ -98,7 +98,7 @@ def use_sift_async_channel(
98
98
  return _use_insecure_sift_async_channel(config, metadata)
99
99
 
100
100
  return grpc_aio.secure_channel(
101
- target=_clean_uri(config["uri"], use_ssl),
101
+ target=parse_host(config["uri"]),
102
102
  credentials=get_ssl_credentials(cert_via_openssl),
103
103
  options=_compute_channel_options(config),
104
104
  interceptors=_compute_sift_async_interceptors(config, metadata),
@@ -112,7 +112,7 @@ def _use_insecure_sift_channel(
112
112
  FOR DEVELOPMENT PURPOSES ONLY
113
113
  """
114
114
  options = _compute_channel_options(config)
115
- api_uri = _clean_uri(config["uri"], False)
115
+ api_uri = parse_host(config["uri"])
116
116
  channel = grpc.insecure_channel(api_uri, options)
117
117
  interceptors = _compute_sift_interceptors(config, metadata)
118
118
  return grpc.intercept_channel(channel, *interceptors)
@@ -125,7 +125,7 @@ def _use_insecure_sift_async_channel(
125
125
  FOR DEVELOPMENT PURPOSES ONLY
126
126
  """
127
127
  return grpc_aio.insecure_channel(
128
- target=_clean_uri(config["uri"], False),
128
+ target=parse_host(config["uri"]),
129
129
  options=_compute_channel_options(config),
130
130
  interceptors=_compute_sift_async_interceptors(config, metadata),
131
131
  )
@@ -205,21 +205,6 @@ def _metadata_async_interceptor(
205
205
  return MetadataAsyncInterceptor(md)
206
206
 
207
207
 
208
- def _clean_uri(uri: str, use_ssl: bool) -> str:
209
- """
210
- This will automatically transform the URI to an acceptable form regardless of whether or not
211
- users included the scheme in the URL or included trailing slashes.
212
- """
213
-
214
- if "http://" in uri or "https://" in uri:
215
- parsed: ParseResult = urlparse(uri)
216
- return parsed.netloc
217
-
218
- full_uri = f"https://{uri}" if use_ssl else f"http://{uri}"
219
- parsed_res: ParseResult = urlparse(full_uri)
220
- return parsed_res.netloc
221
-
222
-
223
208
  def _compute_user_agent() -> str:
224
209
  try:
225
210
  return f"sift_stack_py/{version('sift_stack_py')}"
@@ -143,9 +143,13 @@ class _ReplayState:
143
143
 
144
144
  @dataclass
145
145
  class ReplayResult:
146
- """Result of replaying a log file."""
146
+ """Result of replaying a log file.
147
147
 
148
- report: TestReport
148
+ ``report`` is None on an incremental resume tick that uploaded only steps or
149
+ measurements; the report itself was created on an earlier tick.
150
+ """
151
+
152
+ report: TestReport | None = None
149
153
  steps: list[TestStep] = field(default_factory=list)
150
154
  measurements: list[TestMeasurement] = field(default_factory=list)
151
155
 
@@ -1072,13 +1072,17 @@ class TestResultsLowLevelClient(LowLevelClientBase, WithGrpcClient):
1072
1072
  id_map: dict[str, str],
1073
1073
  state: _ReplayState,
1074
1074
  ) -> None:
1075
- if state.report is None:
1076
- raise ValueError("UpdateTestReport found before CreateTestReport")
1077
1075
  request = UpdateTestReportRequest()
1078
1076
  json_format.Parse(json_str, request)
1079
1077
  request.test_report.test_report_id = self._map_id(
1080
1078
  id_map, request.test_report.test_report_id
1081
1079
  )
1080
+ # Batch/simulate replays the whole log in order, so a missing report means
1081
+ # the log is malformed. Incremental replay may have created the report on an
1082
+ # earlier tick (its real ID lives in id_map), so state.report is legitimately
1083
+ # None here -- the mapped ID is enough to issue the update.
1084
+ if simulate and state.report is None:
1085
+ raise ValueError("UpdateTestReport found before CreateTestReport")
1082
1086
  state.report = await self.update_test_report(
1083
1087
  request=request, simulate=simulate, existing=state.report
1084
1088
  )
@@ -1203,6 +1207,7 @@ class TestResultsLowLevelClient(LowLevelClientBase, WithGrpcClient):
1203
1207
  next tick.
1204
1208
  """
1205
1209
  tracking = LogTracking.load(log_path)
1210
+ resuming = tracking.last_uploaded_line > 0
1206
1211
  id_map = tracking.id_map
1207
1212
  state = _ReplayState()
1208
1213
 
@@ -1221,7 +1226,10 @@ class TestResultsLowLevelClient(LowLevelClientBase, WithGrpcClient):
1221
1226
  tracking.last_uploaded_line += 1
1222
1227
  tracking.save(log_path)
1223
1228
 
1224
- if state.report is None:
1229
+ # On a resume tick the CreateTestReport line was consumed on an earlier
1230
+ # tick, so state.report is expected to be None; the report already exists
1231
+ # on the server. Only a genuine first pass over an empty log is an error.
1232
+ if state.report is None and not resuming:
1225
1233
  raise ValueError("No CreateTestReport found in log file")
1226
1234
 
1227
1235
  return ReplayResult(
@@ -0,0 +1,84 @@
1
+ """Loader for the ``[tool.sift]`` table in a project's ``pyproject.toml``.
2
+
3
+ The pytest plugin consumes this loader to resolve report-content config (under
4
+ ``[tool.sift.pytest.report]``) and SDK-level fallbacks (URIs under
5
+ ``[tool.sift]``). A malformed or missing ``pyproject.toml`` returns ``{}`` so a
6
+ bad config file never aborts the session — the plugin falls back to its
7
+ built-in defaults and surfaces a single warning.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import warnings
13
+ from pathlib import Path
14
+ from typing import TYPE_CHECKING, Any
15
+
16
+ # ``tomllib`` landed in 3.11; ``tomli`` is the same parser packaged for older
17
+ # interpreters and is declared as a conditional install dep on 3.8-3.10.
18
+ try:
19
+ import tomllib # type: ignore[import-not-found,unused-ignore]
20
+ except ImportError: # pragma: no cover - exercised on 3.8-3.10 only
21
+ import tomli as tomllib # type: ignore[no-redef,import-not-found,unused-ignore]
22
+
23
+ if TYPE_CHECKING:
24
+ import pytest
25
+
26
+
27
+ # Bound the upward walk so a misconfigured environment can't trigger an
28
+ # unbounded filesystem traversal looking for a project root that isn't there.
29
+ _MAX_PARENT_WALK = 3
30
+
31
+
32
+ def _find_pyproject(config: pytest.Config) -> Path | None:
33
+ """Locate the active project's ``pyproject.toml``.
34
+
35
+ Order:
36
+ 1. ``config.inipath`` when it is itself a ``pyproject.toml`` (the common
37
+ case: project uses ``[tool.pytest.ini_options]`` so pytest loaded the
38
+ ini settings directly from pyproject).
39
+ 2. ``<config.rootpath>/pyproject.toml``.
40
+ 3. A bounded walk upward from ``rootpath`` for monorepo layouts where
41
+ pytest's rootdir is a subdirectory and the project pyproject lives
42
+ higher up.
43
+ """
44
+ inipath = config.inipath
45
+ if inipath is not None and inipath.name == "pyproject.toml" and inipath.is_file():
46
+ return inipath
47
+ cur = Path(config.rootpath).resolve()
48
+ candidate = cur / "pyproject.toml"
49
+ if candidate.is_file():
50
+ return candidate
51
+ for _ in range(_MAX_PARENT_WALK):
52
+ cur = cur.parent
53
+ candidate = cur / "pyproject.toml"
54
+ if candidate.is_file():
55
+ return candidate
56
+ return None
57
+
58
+
59
+ def load_tool_sift(config: pytest.Config) -> dict[str, Any]:
60
+ """Return the parsed ``[tool.sift]`` table from the project's pyproject.toml.
61
+
62
+ Returns ``{}`` when no pyproject is discoverable, when the file omits the
63
+ ``[tool.sift]`` table, or when parsing fails. A parse / IO failure emits a
64
+ single :class:`SiftPytestPluginWarning` so the session continues with
65
+ defaults rather than aborting on a malformed file.
66
+ """
67
+ pyproject = _find_pyproject(config)
68
+ if pyproject is None:
69
+ return {}
70
+ try:
71
+ with pyproject.open("rb") as fh:
72
+ data = tomllib.load(fh)
73
+ except (OSError, tomllib.TOMLDecodeError) as exc:
74
+ # Deferred import: ``pytest_plugin`` imports this loader, so a
75
+ # top-level import here would close the cycle at module load time.
76
+ from sift_client.pytest_plugin import SiftPytestPluginWarning
77
+
78
+ warnings.warn(
79
+ f"Failed to read {pyproject} for [tool.sift]: {type(exc).__name__}: {exc}",
80
+ SiftPytestPluginWarning,
81
+ stacklevel=2,
82
+ )
83
+ return {}
84
+ return (data.get("tool") or {}).get("sift") or {}
@@ -6,7 +6,7 @@ from requests.adapters import HTTPAdapter
6
6
  from typing_extensions import NotRequired
7
7
  from urllib3.util import Retry
8
8
 
9
- from sift_client._internal.grpc_transport.transport import _clean_uri
9
+ from sift_client._internal.urls import parse_host
10
10
 
11
11
  _DEFAULT_REST_RETRY = Retry(total=3, status_forcelist=[500, 502, 503, 504], backoff_factor=1)
12
12
 
@@ -33,7 +33,7 @@ class SiftRestConfig(TypedDict):
33
33
  def compute_uri(restconf: SiftRestConfig) -> str:
34
34
  uri = restconf["uri"]
35
35
  use_ssl = restconf.get("use_ssl", True)
36
- clean_uri = _clean_uri(uri, use_ssl)
36
+ clean_uri = parse_host(uri)
37
37
 
38
38
  if use_ssl:
39
39
  return f"https://{clean_uri}"
@@ -0,0 +1,55 @@
1
+ """Helpers for turning Sift API endpoints into web-app (frontend) URLs.
2
+
3
+ The Sift frontend can be hosted on several domains and the backend exposes no
4
+ field for its own URL, so the frontend origin is derived client-side from the
5
+ API host. This table mirrors the canonical mapping used by the Grafana
6
+ datasource (sift-stack/sift-grafana-datasource,
7
+ ``src/components/sharelink/getFrontendHostnameDefaults.ts``). Hosts outside the
8
+ table (on-prem and custom deployments) require an explicit override.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from urllib.parse import urlparse
14
+
15
+ # API host (host[:port], no scheme) -> frontend origin (with scheme).
16
+ _API_HOST_TO_FRONTEND_ORIGIN: dict[str, str] = {
17
+ "api.siftstack.com": "https://app.siftstack.com",
18
+ "gov.api.siftstack.com": "https://gov.siftstack.com",
19
+ }
20
+
21
+
22
+ def parse_origin(url: str) -> str:
23
+ """Normalize a URL or bare host into a ``scheme://host[:port]`` origin.
24
+
25
+ Bare hosts (no scheme) are assumed to be ``https``.
26
+ """
27
+ candidate = url if "://" in url else f"https://{url}"
28
+ parsed = urlparse(candidate)
29
+ return f"{parsed.scheme}://{parsed.netloc}".rstrip("/")
30
+
31
+
32
+ def parse_host(url: str) -> str:
33
+ """Extract ``host[:port]`` from a URL or bare host string."""
34
+ candidate = url if "://" in url else f"https://{url}"
35
+ return urlparse(candidate).netloc
36
+
37
+
38
+ def frontend_origin_for_api(api_base_url: str, override: str | None = None) -> str | None:
39
+ """Return the Sift web-app origin for a given API base URL.
40
+
41
+ Args:
42
+ api_base_url: The REST API base URL (e.g. ``https://api.siftstack.com``).
43
+ override: An explicit frontend origin (host or full URL) to use instead
44
+ of the derived value. Set this for on-prem or custom deployments
45
+ whose API host isn't in the built-in mapping.
46
+
47
+ Returns:
48
+ The frontend origin (e.g. ``https://app.siftstack.com``), or ``None``
49
+ when no override is given and the API host isn't recognized.
50
+ """
51
+ if override:
52
+ return parse_origin(override)
53
+ if not api_base_url:
54
+ return None
55
+ return _API_HOST_TO_FRONTEND_ORIGIN.get(parse_host(api_base_url))
@@ -0,0 +1,271 @@
1
+ """HDF5 schema detection.
2
+
3
+ HDF5 files have no single canonical layout, so detection is parameterized
4
+ by an ``Hdf5Schema``: ``ONE_D`` (per-group time dataset + sibling 1D values,
5
+ with an ancestor walk-up), ``TWO_D`` (``[N, 2]`` datasets where col 0 is
6
+ time), or ``COMPOUND`` (struct-like datasets whose first field is time).
7
+ Each detector walks every dataset in the file recursively; datasets that
8
+ don't fit the chosen schema are not included in the resulting config."""
9
+
10
+ from __future__ import annotations
11
+
12
+ from pathlib import Path
13
+ from typing import Callable
14
+
15
+ import h5py
16
+ import numpy as np
17
+
18
+ from sift_client._internal.util.numpy_types import numpy_to_sift_type
19
+ from sift_client.sift_types.data_import import (
20
+ DataTypeKey,
21
+ Hdf5DataColumn,
22
+ Hdf5ImportConfig,
23
+ )
24
+
25
+ # Heuristic attribute names for channel metadata, in priority order. The
26
+ # first non-empty value found on a dataset wins; missing attributes resolve
27
+ # to empty strings.
28
+ _NAME_ATTRS = ("Name", "name", "Title", "title", "Sensor", "sensor", "Channel", "channel")
29
+ _UNIT_ATTRS = ("Unit", "unit", "Units", "units")
30
+ _DESCRIPTION_ATTRS = ("Description", "description")
31
+
32
+ # Per-group time dataset names, case-insensitive, in priority order.
33
+ _TIME_DATASET_NAMES = ("time", "timestamp", "timestamps", "ts")
34
+
35
+
36
+ def _read_string_attr(dataset: h5py.Dataset, candidates: tuple[str, ...]) -> str:
37
+ """Return the first non-empty string attribute among `candidates`."""
38
+ for name in candidates:
39
+ if name not in dataset.attrs:
40
+ continue
41
+ value = dataset.attrs[name]
42
+ if isinstance(value, bytes):
43
+ value = value.decode("utf-8", errors="replace")
44
+ if isinstance(value, str) and value:
45
+ return value
46
+ # h5py returns multi-element string attrs as ndarrays; take the first.
47
+ if isinstance(value, np.ndarray) and value.size > 0:
48
+ first = value.flat[0]
49
+ if isinstance(first, bytes):
50
+ first = first.decode("utf-8", errors="replace")
51
+ if isinstance(first, str) and first:
52
+ return first
53
+ return ""
54
+
55
+
56
+ def _read_channel_metadata(dataset: h5py.Dataset) -> tuple[str, str, str]:
57
+ """Return ``(name, units, description)`` discovered from HDF5 attributes."""
58
+ return (
59
+ _read_string_attr(dataset, _NAME_ATTRS),
60
+ _read_string_attr(dataset, _UNIT_ATTRS),
61
+ _read_string_attr(dataset, _DESCRIPTION_ATTRS),
62
+ )
63
+
64
+
65
+ def _is_compound(dataset: h5py.Dataset) -> bool:
66
+ return dataset.dtype.names is not None and len(dataset.dtype.names) > 1
67
+
68
+
69
+ def _is_1d_non_compound(dataset: h5py.Dataset) -> bool:
70
+ return not _is_compound(dataset) and len(dataset.shape) == 1
71
+
72
+
73
+ def _is_2d_n_by_2(dataset: h5py.Dataset) -> bool:
74
+ return not _is_compound(dataset) and len(dataset.shape) == 2 and dataset.shape[1] == 2
75
+
76
+
77
+ def _path_to_channel_name(path: str) -> str:
78
+ """Sift renders dotted names hierarchically, so ``group1/current`` becomes
79
+ ``group1.current``, with ``current`` shown under a ``group1`` folder."""
80
+ return path.replace("/", ".")
81
+
82
+
83
+ def _make_name_deduper() -> Callable[[str, str], str]:
84
+ """Return a callable that resolves duplicate channel names by appending
85
+ the dataset's dotted path. First claim of a name wins; later claims of
86
+ the same name get the fallback suffix appended."""
87
+ used: set[str] = set()
88
+
89
+ def dedupe(base_name: str, fallback_suffix: str) -> str:
90
+ name = f"{base_name}.{fallback_suffix}" if base_name in used else base_name
91
+ used.add(name)
92
+ return name
93
+
94
+ return dedupe
95
+
96
+
97
+ def _collect_datasets(h5file: h5py.File) -> list[h5py.Dataset]:
98
+ """Recursively walk every dataset in the file."""
99
+ out: list[h5py.Dataset] = []
100
+
101
+ def visit(_name: str, obj: object) -> None:
102
+ if isinstance(obj, h5py.Dataset):
103
+ out.append(obj)
104
+
105
+ h5file.visititems(visit)
106
+ return out
107
+
108
+
109
+ def _group_by_parent(datasets: list[h5py.Dataset]) -> dict[str, list[h5py.Dataset]]:
110
+ """Group datasets by their parent group path (``""`` for root-level)."""
111
+ out: dict[str, list[h5py.Dataset]] = {}
112
+ for ds in datasets:
113
+ out.setdefault(ds.name.lstrip("/").rpartition("/")[0], []).append(ds)
114
+ return out
115
+
116
+
117
+ def _resolve_ancestor_time(group_path: str, per_group_time: dict[str, str]) -> str:
118
+ """Return the closest-ancestor time dataset path for ``group_path``,
119
+ walking up to the root. Empty string if no ancestor has one."""
120
+ cursor = group_path
121
+ while True:
122
+ found = per_group_time.get(cursor)
123
+ if found:
124
+ return found
125
+ if cursor == "":
126
+ return ""
127
+ slash = cursor.rfind("/")
128
+ cursor = "" if slash < 0 else cursor[:slash]
129
+
130
+
131
+ def _build_one_d_configs(datasets: list[h5py.Dataset]) -> list[Hdf5DataColumn]:
132
+ """1D non-compound schema: at each group, pick a time dataset (by name)
133
+ and pair every other 1D dataset in that group as a value channel.
134
+ Datasets that aren't 1D non-compound are not included."""
135
+
136
+ def identify_time_dataset(group: list[h5py.Dataset]) -> h5py.Dataset | None:
137
+ """Pick the group's time dataset by leaf name, case-insensitive, in
138
+ priority order. Returns ``None`` if no candidate matches; callers
139
+ fall back to an ancestor group's time before giving up."""
140
+ for candidate in _TIME_DATASET_NAMES:
141
+ for ds in group:
142
+ if ds.name.rsplit("/", 1)[-1].lower() == candidate:
143
+ return ds
144
+ return None
145
+
146
+ columns: list[Hdf5DataColumn] = []
147
+ dedupe = _make_name_deduper()
148
+
149
+ one_d = [ds for ds in datasets if _is_1d_non_compound(ds)]
150
+ grouped = _group_by_parent(one_d)
151
+
152
+ # First pass: each group's own time dataset (if any).
153
+ per_group_time: dict[str, str] = {}
154
+ for group_path, group in grouped.items():
155
+ time_ds = identify_time_dataset(group)
156
+ if time_ds is not None:
157
+ per_group_time[group_path] = time_ds.name.lstrip("/")
158
+
159
+ for group_path, group in grouped.items():
160
+ own_time_path = per_group_time.get(group_path)
161
+ time_path = own_time_path or _resolve_ancestor_time(group_path, per_group_time)
162
+ for ds in group:
163
+ ds_path = ds.name.lstrip("/")
164
+ if own_time_path and ds_path == own_time_path:
165
+ continue
166
+ name, units, description = _read_channel_metadata(ds)
167
+ fallback = _path_to_channel_name(ds_path)
168
+ columns.append(
169
+ Hdf5DataColumn(
170
+ name=dedupe(name or fallback, fallback),
171
+ data_type=numpy_to_sift_type(ds.dtype),
172
+ units=units,
173
+ description=description,
174
+ time_dataset=time_path,
175
+ value_dataset=ds_path,
176
+ time_index=0,
177
+ value_index=0,
178
+ )
179
+ )
180
+
181
+ return columns
182
+
183
+
184
+ def _build_two_d_configs(datasets: list[h5py.Dataset]) -> list[Hdf5DataColumn]:
185
+ """2D schema: every dataset with shape ``[N, 2]`` becomes one channel
186
+ (col 0 = time, col 1 = value). Other shapes are not included."""
187
+ columns: list[Hdf5DataColumn] = []
188
+ dedupe = _make_name_deduper()
189
+
190
+ for ds in datasets:
191
+ if not _is_2d_n_by_2(ds):
192
+ continue
193
+ ds_path = ds.name.lstrip("/")
194
+ name, units, description = _read_channel_metadata(ds)
195
+ fallback = _path_to_channel_name(ds_path)
196
+ columns.append(
197
+ Hdf5DataColumn(
198
+ name=dedupe(name or fallback, fallback),
199
+ data_type=numpy_to_sift_type(ds.dtype),
200
+ units=units,
201
+ description=description,
202
+ time_dataset=ds_path,
203
+ value_dataset=ds_path,
204
+ time_index=0,
205
+ value_index=1,
206
+ )
207
+ )
208
+
209
+ return columns
210
+
211
+
212
+ def _build_compound_configs(datasets: list[h5py.Dataset]) -> list[Hdf5DataColumn]:
213
+ """Compound schema: every compound dataset becomes one channel per
214
+ non-time member. First member is time. Non-compound datasets are not included."""
215
+ columns: list[Hdf5DataColumn] = []
216
+ dedupe = _make_name_deduper()
217
+
218
+ for ds in datasets:
219
+ if not _is_compound(ds):
220
+ continue
221
+ field_names = ds.dtype.names
222
+ assert field_names is not None # guaranteed by _is_compound
223
+ time_field = field_names[0]
224
+ value_fields = field_names[1:]
225
+ ds_path = ds.name.lstrip("/")
226
+ name, units, description = _read_channel_metadata(ds)
227
+ dataset_name = name or _path_to_channel_name(ds_path)
228
+
229
+ for value_field in value_fields:
230
+ base_name = f"{dataset_name}.{value_field}" if len(value_fields) > 1 else dataset_name
231
+ fallback_suffix = f"{_path_to_channel_name(ds_path)}.{value_field}"
232
+ columns.append(
233
+ Hdf5DataColumn(
234
+ name=dedupe(base_name, fallback_suffix),
235
+ data_type=numpy_to_sift_type(ds.dtype[value_field]),
236
+ units=units,
237
+ description=description,
238
+ time_dataset=ds_path,
239
+ value_dataset=ds_path,
240
+ time_index=0,
241
+ value_index=0,
242
+ time_field=time_field,
243
+ value_field=value_field,
244
+ )
245
+ )
246
+
247
+ return columns
248
+
249
+
250
+ _BUILDERS: dict[DataTypeKey, Callable[[list[h5py.Dataset]], list[Hdf5DataColumn]]] = {
251
+ DataTypeKey.HDF5_ONE_D: _build_one_d_configs,
252
+ DataTypeKey.HDF5_TWO_D: _build_two_d_configs,
253
+ DataTypeKey.HDF5_COMPOUND: _build_compound_configs,
254
+ }
255
+
256
+
257
+ def detect_hdf5_config(file_path: str | Path, data_type_key: DataTypeKey) -> Hdf5ImportConfig:
258
+ """Detect an HDF5 import config under the given variant. Datasets that
259
+ don't fit the chosen variant are not included. ``time_format`` is always
260
+ left unset: HDF5 timestamps aren't self-describing, so the caller must set
261
+ ``config.time_format`` before importing."""
262
+ if data_type_key not in _BUILDERS:
263
+ raise ValueError(
264
+ f"detect_hdf5_config requires an HDF5 DataTypeKey variant "
265
+ f"(HDF5_ONE_D, HDF5_TWO_D, or HDF5_COMPOUND); got {data_type_key}."
266
+ )
267
+ path = Path(file_path)
268
+ with h5py.File(path, "r") as h5file:
269
+ columns = _BUILDERS[data_type_key](_collect_datasets(h5file))
270
+
271
+ return Hdf5ImportConfig(asset_name="", data=columns)
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from sift_client._internal.urls import frontend_origin_for_api
3
4
  from sift_client.resources import (
4
5
  AssetsAPI,
5
6
  AssetsAPIAsync,
@@ -124,6 +125,7 @@ class SiftClient(
124
125
  grpc_url: str | None = None,
125
126
  rest_url: str | None = None,
126
127
  connection_config: SiftConnectionConfig | None = None,
128
+ app_url: str | None = None,
127
129
  ):
128
130
  """Initialize the SiftClient with specific connection parameters or a connection_config.
129
131
 
@@ -132,6 +134,10 @@ class SiftClient(
132
134
  grpc_url: The Sift gRPC API URL.
133
135
  rest_url: The Sift REST API URL.
134
136
  connection_config: A SiftConnectionConfig object to configure the connection behavior of the SiftClient.
137
+ app_url: The Sift web-app origin (e.g. ``https://app.siftstack.com``).
138
+ Set this for on-prem or custom deployments whose API host can't be
139
+ mapped to a frontend automatically; see the ``app_url`` property.
140
+ A value here takes precedence over ``connection_config.app_url``.
135
141
  """
136
142
  if not (api_key and grpc_url and rest_url) and not connection_config:
137
143
  raise ValueError(
@@ -152,6 +158,12 @@ class SiftClient(
152
158
  WithGrpcClient.__init__(self, grpc_client=grpc_client)
153
159
  WithRestClient.__init__(self, rest_client=rest_client)
154
160
 
161
+ # Explicit web-app origin override; falls back to the connection config's
162
+ # value, then to host-based derivation in the ``app_url`` property.
163
+ self._app_url: str | None = app_url or (
164
+ connection_config.app_url if connection_config else None
165
+ )
166
+
155
167
  # When set, test-results writes return synthesized responses without
156
168
  # contacting Sift. Read by `TestResultsAPIAsync._simulate`. Used by the
157
169
  # pytest plugin's ``--sift-disabled`` mode.
@@ -198,3 +210,18 @@ class SiftClient(
198
210
  def rest_client(self) -> RestClient:
199
211
  """The REST client used by the SiftClient for making REST API calls."""
200
212
  return self._rest_client
213
+
214
+ @property
215
+ def app_url(self) -> str | None:
216
+ """The Sift web-app origin for this client, or None if it can't be determined.
217
+
218
+ Uses the explicit override passed at construction when set, otherwise
219
+ derives the origin from the REST host for known Sift deployments (e.g.
220
+ ``https://api.siftstack.com`` -> ``https://app.siftstack.com``). Returns
221
+ None for unrecognized hosts with no override.
222
+
223
+ # TODO: Add a ``WithAppPage`` mixin on BaseType so resources (TestReport,
224
+ # Run, ...) can expose their own web-app link from ``_client.app_url`` plus
225
+ # a per-type path, instead of callers assembling paths by hand.
226
+ """
227
+ return frontend_origin_for_api(self.rest_client.base_url, override=self._app_url)