hiddenlayer-sdk 3.5.0__tar.gz → 3.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/.gitignore +1 -0
  2. hiddenlayer_sdk-3.6.0/.release-please-manifest.json +3 -0
  3. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/CHANGELOG.md +57 -0
  4. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/PKG-INFO +9 -2
  5. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/README.md +7 -0
  6. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/api.md +7 -7
  7. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/pyproject.toml +3 -2
  8. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/__init__.py +10 -1
  9. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_base_client.py +4 -0
  10. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_client.py +19 -3
  11. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_compat.py +9 -2
  12. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_qs.py +4 -1
  13. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/__init__.py +1 -0
  14. hiddenlayer_sdk-3.6.0/src/hiddenlayer/_utils/_path.py +127 -0
  15. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_utils.py +3 -2
  16. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_version.py +1 -1
  17. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/__init__.py +4 -0
  18. hiddenlayer_sdk-3.6.0/src/hiddenlayer/lib/_beta.py +45 -0
  19. hiddenlayer_sdk-3.6.0/src/hiddenlayer/lib/_beta_endpoints.py +11 -0
  20. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/community_scan.py +11 -4
  21. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/model_scan.py +10 -3
  22. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/scan_utils.py +20 -0
  23. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/evaluations/red_team.py +53 -19
  24. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/models/models.py +5 -4
  25. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/jobs.py +3 -5
  26. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/results.py +3 -2
  27. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/upload/file.py +5 -5
  28. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/upload/upload.py +3 -3
  29. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/sensors.py +7 -7
  30. hiddenlayer_sdk-3.6.0/src/hiddenlayer/types/evaluations/red_team_retrieve_evaluation_results_response.py +48 -0
  31. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_status_response.py +0 -6
  32. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/interaction_analyze_params.py +3 -6
  33. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/job_list_response.py +1 -1
  34. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/job_request_params.py +1 -1
  35. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/scan_job.py +1 -1
  36. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/scan_report.py +1 -1
  37. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/conftest.py +21 -1
  38. hiddenlayer_sdk-3.6.0/tests/test_beta.py +62 -0
  39. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_client.py +48 -0
  40. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_extract_files.py +9 -0
  41. hiddenlayer_sdk-3.6.0/tests/test_utils/test_path.py +89 -0
  42. hiddenlayer_sdk-3.5.0/.release-please-manifest.json +0 -3
  43. hiddenlayer_sdk-3.5.0/src/hiddenlayer/types/evaluations/red_team_retrieve_evaluation_results_response.py +0 -20
  44. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/CODE_OF_CONDUCT.md +0 -0
  45. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/CONTRIBUTING.md +0 -0
  46. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/LICENSE +0 -0
  47. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/SECURITY.md +0 -0
  48. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/bin/check-release-environment +0 -0
  49. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/bin/publish-jfrog +0 -0
  50. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/bin/publish-pypi +0 -0
  51. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/examples/.keep +0 -0
  52. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/examples/demo.py +0 -0
  53. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/noxfile.py +0 -0
  54. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/release-please-config.json +0 -0
  55. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/requirements-dev.lock +0 -0
  56. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/requirements.lock +0 -0
  57. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_constants.py +0 -0
  58. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_exceptions.py +0 -0
  59. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_files.py +0 -0
  60. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_models.py +0 -0
  61. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_oauth2.py +0 -0
  62. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_resource.py +0 -0
  63. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_response.py +0 -0
  64. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_streaming.py +0 -0
  65. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_types.py +0 -0
  66. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_compat.py +0 -0
  67. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_datetime_parse.py +0 -0
  68. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_json.py +0 -0
  69. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_logs.py +0 -0
  70. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_proxy.py +0 -0
  71. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_reflection.py +0 -0
  72. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_resources_proxy.py +0 -0
  73. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_streams.py +0 -0
  74. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_sync.py +0 -0
  75. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_transform.py +0 -0
  76. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/_utils/_typing.py +0 -0
  77. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/.keep +0 -0
  78. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/evaluation_sessions.py +0 -0
  79. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/red_team_exceptions.py +0 -0
  80. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/lib/red_team_session.py +0 -0
  81. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/pagination.py +0 -0
  82. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/py.typed +0 -0
  83. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/__init__.py +0 -0
  84. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/evaluations/__init__.py +0 -0
  85. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/evaluations/evaluations.py +0 -0
  86. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/interactions.py +0 -0
  87. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/models/__init__.py +0 -0
  88. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/models/cards.py +0 -0
  89. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/prompt_analyzer.py +0 -0
  90. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/__init__.py +0 -0
  91. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/scans.py +0 -0
  92. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/resources/scans/upload/__init__.py +0 -0
  93. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/__init__.py +0 -0
  94. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/__init__.py +0 -0
  95. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/red_team_create_params.py +0 -0
  96. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/red_team_create_response.py +0 -0
  97. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_next_action_response.py +0 -0
  98. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/red_team_submit_target_response_params.py +0 -0
  99. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/evaluations/red_team_submit_target_response_response.py +0 -0
  100. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/interaction_analyze_response.py +0 -0
  101. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/model_retrieve_response.py +0 -0
  102. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/models/__init__.py +0 -0
  103. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/models/card_list_params.py +0 -0
  104. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/models/card_list_response.py +0 -0
  105. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/prompt_analyzer_create_params.py +0 -0
  106. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/prompt_analyzer_create_response.py +0 -0
  107. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/__init__.py +0 -0
  108. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/job_list_params.py +0 -0
  109. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/job_retrieve_params.py +0 -0
  110. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/result_sarif_response.py +0 -0
  111. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/upload/__init__.py +0 -0
  112. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/upload/file_add_response.py +0 -0
  113. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/upload/file_complete_response.py +0 -0
  114. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/upload_complete_all_response.py +0 -0
  115. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/upload_start_params.py +0 -0
  116. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/scans/upload_start_response.py +0 -0
  117. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_create_params.py +0 -0
  118. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_create_response.py +0 -0
  119. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_query_params.py +0 -0
  120. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_query_response.py +0 -0
  121. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_retrieve_response.py +0 -0
  122. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_update_params.py +0 -0
  123. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/src/hiddenlayer/types/sensor_update_response.py +0 -0
  124. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/__init__.py +0 -0
  125. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/__init__.py +0 -0
  126. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/evaluations/__init__.py +0 -0
  127. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/evaluations/test_red_team.py +0 -0
  128. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/models/__init__.py +0 -0
  129. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/models/test_cards.py +0 -0
  130. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/scans/__init__.py +0 -0
  131. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/scans/test_jobs.py +0 -0
  132. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/scans/test_results.py +0 -0
  133. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/scans/test_upload.py +0 -0
  134. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/scans/upload/__init__.py +0 -0
  135. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/scans/upload/test_file.py +0 -0
  136. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/test_interactions.py +0 -0
  137. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/test_models.py +0 -0
  138. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/test_prompt_analyzer.py +0 -0
  139. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/api_resources/test_sensors.py +0 -0
  140. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/sample_file.txt +0 -0
  141. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_community_scan.py +0 -0
  142. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_deepcopy.py +0 -0
  143. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_files.py +0 -0
  144. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_model_scan.py +0 -0
  145. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_models.py +0 -0
  146. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_qs.py +0 -0
  147. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_red_team_session.py +0 -0
  148. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_required_args.py +0 -0
  149. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_response.py +0 -0
  150. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_streaming.py +0 -0
  151. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_transform.py +0 -0
  152. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_utils/test_datetime_parse.py +0 -0
  153. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_utils/test_json.py +0 -0
  154. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_utils/test_proxy.py +0 -0
  155. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/test_utils/test_typing.py +0 -0
  156. {hiddenlayer_sdk-3.5.0 → hiddenlayer_sdk-3.6.0}/tests/utils.py +0 -0
@@ -1,4 +1,5 @@
1
1
  .prism.log
2
+ .stdy.log
2
3
  _dev
3
4
 
4
5
  __pycache__
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "3.6.0"
3
+ }
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.6.0 (2026-04-14)
4
+
5
+ Full Changelog: [v3.5.0...v3.6.0](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.5.0...v3.6.0)
6
+
7
+ ### Features
8
+
9
+ * add beta instability warnings for unstable SDK methods ([#186](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/186)) ([e56488a](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e56488a532201b4f6cc46c5a0be68a45614b1734))
10
+ * **api:** add runtime security evaluations endpoints ([2433787](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/2433787d248b222da7a077b2ef1efd54f5116f7e))
11
+ * **api:** api update ([6b894b8](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/6b894b89ab4cef087e0fc7df4a62913c4b1b1710))
12
+ * **api:** api update ([dd91242](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/dd912420f1d2e8574454cdfa754f4817b7a2423e))
13
+ * **api:** api update ([825a274](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/825a2742d0b674b392e37c99be54c576ff9be34c))
14
+ * **api:** api update ([c43deaa](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/c43deaa74339cc7f3f70cb4b5e26c027fe975896))
15
+ * **api:** api update ([716c68c](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/716c68cef3e9ae8d15631d417335c3f387bedc72))
16
+ * **api:** api update ([98a52fa](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/98a52fad11b3e42b9b576738601743f59ad8752d))
17
+ * **api:** finalize runtime security endpoints ([e83726c](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e83726c4a62ede87be9222e1f3acbbd0c27e1f99))
18
+ * **internal:** implement indices array format for query and form serialization ([05135c2](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/05135c262a3688319bfd7508452b1c101d9901c4))
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **beta:** harden CI tests against codegen churn ([#191](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/191)) ([8f85aec](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/8f85aec226a6a7278aa388d30f74d7735031b9cb))
24
+ * **client:** preserve hardcoded query params when merging with user params ([90ad63a](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/90ad63ae4aea92158416a5e1101a3d0496a20646))
25
+ * correct async method indentation in beta warning patcher ([2af3e63](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/2af3e6358565aaca1a3b3069868f2af090db7f92))
26
+ * **deps:** bump minimum typing-extensions version ([53b0b0e](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/53b0b0edfaf7a7dea0b097333fac0ecdc9a16bcb))
27
+ * ensure file data are only sent as 1 parameter ([1ea7561](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/1ea756124f32f0f49ba9d73bcdc2c4d63931c649))
28
+ * **pydantic:** do not pass `by_alias` unless set ([86f9db3](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/86f9db32c94ff8358bf294f14a54a460d1d7444b))
29
+ * sanitize endpoint path params ([ea53526](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/ea5352653b0708eaa5f495a598cdf19935d26fac))
30
+ * **tests:** correct setup of OAuth 2 Client Credentials tests ([b3887a1](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/b3887a1e39f05e01d5e16c768ef96ac6ca6e98ed))
31
+
32
+
33
+ ### Chores
34
+
35
+ * **ci:** skip lint on metadata-only changes ([803a48b](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/803a48bed50ae657bfe8efdbfce86969d57ac96d))
36
+ * **ci:** skip uploading artifacts on stainless-internal branches ([e901a9f](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e901a9f5a6af3b5650d0002b9dd18b7ba954c38d))
37
+ * **deps:** bump actions/setup-node from 4 to 6 ([5abc090](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/5abc090fa35bc1efd1422cd8455aa369fed72fc4))
38
+ * **deps:** bump github/codeql-action from 4.32.6 to 4.35.1 ([6715471](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/67154712c4497ee3d90fea9aa9632d2ad6fa763d))
39
+ * **deps:** bump step-security/harden-runner from 2.15.1 to 2.16.1 ([58738e5](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/58738e54c1dd7cfe4b710e0cc75a246598c6b9f7))
40
+ * **internal:** codegen related update ([e2b17fd](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e2b17fd099188441b0d296a1a745a930f9953665))
41
+ * **internal:** tweak CI branches ([535faac](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/535faacf763992576b28266f92e226be1f07fb09))
42
+ * **internal:** update gitignore ([bf2dcbe](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/bf2dcbe99c112ab5869ecff719ae66c93cacfc15))
43
+ * patch beta warnings [skip ci] ([ff2ae92](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/ff2ae92be61ae0838e24d28632e38aa024ad28cb))
44
+ * regenerate beta endpoint registry [skip ci] ([5aded1f](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/5aded1f3c1b0aa3bc4ae76137faf6987a71c0db2))
45
+ * regenerate beta endpoint registry [skip ci] ([126b13e](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/126b13ea66294a7c1a2d31e8edfcd336552b245e))
46
+ * regenerate beta endpoint registry [skip ci] ([24d568e](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/24d568e9fc74b6a0c044ea9a74120e4504fe1b16))
47
+ * remove stale version comments from SHA-pinned actions ([#184](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/184)) ([cf07e32](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/cf07e322e7b4674fe3ef622e491278b0346e5e7e))
48
+
49
+
50
+ ### Documentation
51
+
52
+ * **readme:** add Beta APIs section ([#185](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/185)) ([b1381e3](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/b1381e389f6e7ee59ba51ff00ce84b4a43f97c35))
53
+
54
+
55
+ ### Refactors
56
+
57
+ * **client:** move beta warnings to _prepare_options interceptor ([#190](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/190)) ([893ee22](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/893ee22fdda949ebab80d66d70b99accb79aded2))
58
+ * **types:** use `extra_items` from PEP 728 ([e5ee89f](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e5ee89fccbefe680538b8b3b06871dfba90d1474))
59
+
3
60
  ## 3.5.0 (2026-03-03)
4
61
 
5
62
  Full Changelog: [v3.4.0...v3.5.0](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.4.0...v3.5.0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hiddenlayer-sdk
3
- Version: 3.5.0
3
+ Version: 3.6.0
4
4
  Summary: The official Python library for the hiddenlayer API
5
5
  Project-URL: Homepage, https://github.com/hiddenlayerai/hiddenlayer-sdk-python
6
6
  Project-URL: Repository, https://github.com/hiddenlayerai/hiddenlayer-sdk-python
@@ -30,7 +30,7 @@ Requires-Dist: requests-auth>=8.0.0
30
30
  Requires-Dist: requests>=2.32.4
31
31
  Requires-Dist: sniffio
32
32
  Requires-Dist: types-requests>=2.32.0.20241016
33
- Requires-Dist: typing-extensions<5,>=4.10
33
+ Requires-Dist: typing-extensions<5,>=4.14
34
34
  Provides-Extra: aiohttp
35
35
  Requires-Dist: aiohttp; extra == 'aiohttp'
36
36
  Requires-Dist: httpx-aiohttp>=0.1.9; extra == 'aiohttp'
@@ -51,6 +51,13 @@ It is generated with [Stainless](https://www.stainless.com/).
51
51
 
52
52
  The REST API documentation can be found on [dev.hiddenlayer.ai](https://dev.hiddenlayer.ai). The full API of this library can be found in [api.md](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/tree/main/api.md).
53
53
 
54
+ ## Beta APIs
55
+
56
+ Some HiddenLayer APIs are marked as **Beta**, meaning they are not yet generally available (GA) or production ready. Beta APIs can be used in a production environment, but at your own risk and discretion. For full details, see the [Beta API Guidelines](https://dev.hiddenlayer.ai/docs/beta-api-faq) on the developer portal.
57
+
58
+ - HiddenLayer does not provide compatibility guarantees for Beta APIs. Breaking changes may occur at any time.
59
+ - SDK functions and types associated with Beta APIs are excluded when determining semver release versions.
60
+
54
61
  ## Installation
55
62
 
56
63
  ```sh
@@ -13,6 +13,13 @@ It is generated with [Stainless](https://www.stainless.com/).
13
13
 
14
14
  The REST API documentation can be found on [dev.hiddenlayer.ai](https://dev.hiddenlayer.ai). The full API of this library can be found in [api.md](api.md).
15
15
 
16
+ ## Beta APIs
17
+
18
+ Some HiddenLayer APIs are marked as **Beta**, meaning they are not yet generally available (GA) or production ready. Beta APIs can be used in a production environment, but at your own risk and discretion. For full details, see the [Beta API Guidelines](https://dev.hiddenlayer.ai/docs/beta-api-faq) on the developer portal.
19
+
20
+ - HiddenLayer does not provide compatibility guarantees for Beta APIs. Breaking changes may occur at any time.
21
+ - SDK functions and types associated with Beta APIs are excluded when determining semver release versions.
22
+
16
23
  ## Installation
17
24
 
18
25
  ```sh
@@ -43,19 +43,19 @@ from hiddenlayer.types.evaluations import (
43
43
 
44
44
  Methods:
45
45
 
46
- - <code title="post /evaluations/v1-beta/red-team">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">create</a>(\*\*<a href="src/hiddenlayer/types/evaluations/red_team_create_params.py">params</a>) -> <a href="./src/hiddenlayer/types/evaluations/red_team_create_response.py">RedTeamCreateResponse</a></code>
47
- - <code title="get /evaluations/v1-beta/red-team/{workflow_id}">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">retrieve_evaluation_results</a>(workflow_id) -> <a href="./src/hiddenlayer/types/evaluations/red_team_retrieve_evaluation_results_response.py">RedTeamRetrieveEvaluationResultsResponse</a></code>
48
- - <code title="get /evaluations/v1-beta/red-team/{workflow_id}/next-action">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">retrieve_next_action</a>(workflow_id) -> <a href="./src/hiddenlayer/types/evaluations/red_team_retrieve_next_action_response.py">RedTeamRetrieveNextActionResponse</a></code>
49
- - <code title="get /evaluations/v1-beta/red-team/{workflow_id}/status">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">retrieve_status</a>(workflow_id) -> <a href="./src/hiddenlayer/types/evaluations/red_team_retrieve_status_response.py">RedTeamRetrieveStatusResponse</a></code>
50
- - <code title="post /evaluations/v1-beta/red-team/{workflow_id}/target-response">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">submit_target_response</a>(workflow_id, \*\*<a href="src/hiddenlayer/types/evaluations/red_team_submit_target_response_params.py">params</a>) -> <a href="./src/hiddenlayer/types/evaluations/red_team_submit_target_response_response.py">RedTeamSubmitTargetResponseResponse</a></code>
51
- - <code title="post /evaluations/v1-beta/red-team/terminations/{workflow_id}">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">terminate</a>(workflow_id) -> None</code>
46
+ - <code title="post /evaluations/v1/red-team">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">create</a>(\*\*<a href="src/hiddenlayer/types/evaluations/red_team_create_params.py">params</a>) -> <a href="./src/hiddenlayer/types/evaluations/red_team_create_response.py">RedTeamCreateResponse</a></code>
47
+ - <code title="get /evaluations/v1/red-team/{workflow_id}">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">retrieve_evaluation_results</a>(workflow_id) -> <a href="./src/hiddenlayer/types/evaluations/red_team_retrieve_evaluation_results_response.py">RedTeamRetrieveEvaluationResultsResponse</a></code>
48
+ - <code title="get /evaluations/v1/red-team/{workflow_id}/next-action">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">retrieve_next_action</a>(workflow_id) -> <a href="./src/hiddenlayer/types/evaluations/red_team_retrieve_next_action_response.py">RedTeamRetrieveNextActionResponse</a></code>
49
+ - <code title="get /evaluations/v1/red-team/{workflow_id}/status">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">retrieve_status</a>(workflow_id) -> <a href="./src/hiddenlayer/types/evaluations/red_team_retrieve_status_response.py">RedTeamRetrieveStatusResponse</a></code>
50
+ - <code title="post /evaluations/v1/red-team/{workflow_id}/target-response">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">submit_target_response</a>(workflow_id, \*\*<a href="src/hiddenlayer/types/evaluations/red_team_submit_target_response_params.py">params</a>) -> <a href="./src/hiddenlayer/types/evaluations/red_team_submit_target_response_response.py">RedTeamSubmitTargetResponseResponse</a></code>
51
+ - <code title="post /evaluations/v1/jobs/{workflow_id}/termination">client.evaluations.red_team.<a href="./src/hiddenlayer/resources/evaluations/red_team.py">terminate</a>(workflow_id) -> None</code>
52
52
 
53
53
  # PromptAnalyzer
54
54
 
55
55
  Types:
56
56
 
57
57
  ```python
58
- from hiddenlayer.types import PromptAnalyzerCreateResponse, PromptAnalyzerCreateParams
58
+ from hiddenlayer.types import PromptAnalyzerCreateResponse
59
59
  ```
60
60
 
61
61
  Methods:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hiddenlayer-sdk"
3
- version = "3.5.0"
3
+ version = "3.6.0"
4
4
  description = "The official Python library for the hiddenlayer API"
5
5
  dynamic = ["readme"]
6
6
  license = {text = "Apache-2.0"}
@@ -11,7 +11,7 @@ authors = [
11
11
  dependencies = [
12
12
  "httpx>=0.23.0, <1",
13
13
  "pydantic>=1.9.0, <3",
14
- "typing-extensions>=4.10, <5",
14
+ "typing-extensions>=4.14, <5",
15
15
  "anyio>=3.5.0, <5",
16
16
  "distro>=1.7.0, <2",
17
17
  "sniffio",
@@ -140,6 +140,7 @@ xfail_strict = true
140
140
  asyncio_mode = "auto"
141
141
  asyncio_default_fixture_loop_scope = "session"
142
142
  filterwarnings = [
143
+ "default::hiddenlayer.lib._beta.BetaWarning",
143
144
  "error"
144
145
  ]
145
146
 
@@ -3,7 +3,14 @@
3
3
  import typing as _t
4
4
 
5
5
  from . import types
6
- from .lib import ModelScanner, CommunityScanner, AsyncModelScanner, AsyncCommunityScanner
6
+ from .lib import (
7
+ BetaWarning,
8
+ ModelScanner,
9
+ CommunityScanner,
10
+ AsyncModelScanner,
11
+ AsyncCommunityScanner,
12
+ warn_beta,
13
+ )
7
14
  from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given
8
15
  from ._utils import file_from_path
9
16
  from ._client import (
@@ -46,6 +53,8 @@ __all__ = [
46
53
  "__version__",
47
54
  "__title__",
48
55
  "NoneType",
56
+ "BetaWarning",
57
+ "warn_beta",
49
58
  "CommunityScanner",
50
59
  "AsyncCommunityScanner",
51
60
  "ModelScanner",
@@ -540,6 +540,10 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
540
540
  files = cast(HttpxRequestFiles, ForceMultipartDict())
541
541
 
542
542
  prepared_url = self._prepare_url(options.url)
543
+ # preserve hard-coded query params from the url
544
+ if params and prepared_url.query:
545
+ params = {**dict(prepared_url.params.items()), **params}
546
+ prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0])
543
547
  if "_" in prepared_url.host:
544
548
  # work around https://github.com/encode/httpx/discussions/2880
545
549
  kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")}
@@ -21,6 +21,7 @@ from ._types import (
21
21
  )
22
22
  from ._utils import is_given, get_async_library
23
23
  from ._compat import cached_property
24
+ from ._models import FinalRequestOptions
24
25
  from ._oauth2 import OAuth2ClientCredentials, make_oauth2
25
26
  from ._version import __version__
26
27
  from ._streaming import Stream as Stream, AsyncStream as AsyncStream
@@ -33,16 +34,18 @@ from ._base_client import (
33
34
 
34
35
  if TYPE_CHECKING:
35
36
  from .resources import scans, models, sensors, evaluations, interactions, prompt_analyzer
36
- from .lib.model_scan import ModelScanner, AsyncModelScanner
37
37
  from .resources.sensors import SensorsResource, AsyncSensorsResource
38
- from .lib.community_scan import CommunityScanner, AsyncCommunityScanner
39
38
  from .resources.scans.scans import ScansResource, AsyncScansResource
40
39
  from .resources.interactions import InteractionsResource, AsyncInteractionsResource
41
- from .lib.evaluation_sessions import EvaluationSessionsResource, AsyncEvaluationSessionsResource
42
40
  from .resources.models.models import ModelsResource, AsyncModelsResource
43
41
  from .resources.prompt_analyzer import PromptAnalyzerResource, AsyncPromptAnalyzerResource
44
42
  from .resources.evaluations.evaluations import EvaluationsResource, AsyncEvaluationsResource
45
43
 
44
+ if TYPE_CHECKING:
45
+ from .lib.model_scan import ModelScanner, AsyncModelScanner
46
+ from .lib.community_scan import CommunityScanner, AsyncCommunityScanner
47
+ from .lib.evaluation_sessions import EvaluationSessionsResource, AsyncEvaluationSessionsResource
48
+
46
49
  __all__ = [
47
50
  "ENVIRONMENTS",
48
51
  "Timeout",
@@ -256,6 +259,12 @@ class HiddenLayer(SyncAPIClient):
256
259
  return True
257
260
  return super()._should_retry(response)
258
261
 
262
+ @override
263
+ def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions:
264
+ from .lib._beta import check_beta_endpoint
265
+
266
+ check_beta_endpoint(options.url)
267
+ return options
259
268
 
260
269
  def copy(
261
270
  self,
@@ -543,6 +552,13 @@ class AsyncHiddenLayer(AsyncAPIClient):
543
552
  return True
544
553
  return super()._should_retry(response)
545
554
 
555
+ @override
556
+ async def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions:
557
+ from .lib._beta import check_beta_endpoint
558
+
559
+ check_beta_endpoint(options.url)
560
+ return options
561
+
546
562
  def copy(
547
563
  self,
548
564
  *,
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast, overload
4
4
  from datetime import date, datetime
5
- from typing_extensions import Self, Literal
5
+ from typing_extensions import Self, Literal, TypedDict
6
6
 
7
7
  import pydantic
8
8
  from pydantic.fields import FieldInfo
@@ -131,6 +131,10 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str:
131
131
  return model.model_dump_json(indent=indent)
132
132
 
133
133
 
134
+ class _ModelDumpKwargs(TypedDict, total=False):
135
+ by_alias: bool
136
+
137
+
134
138
  def model_dump(
135
139
  model: pydantic.BaseModel,
136
140
  *,
@@ -142,6 +146,9 @@ def model_dump(
142
146
  by_alias: bool | None = None,
143
147
  ) -> dict[str, Any]:
144
148
  if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
149
+ kwargs: _ModelDumpKwargs = {}
150
+ if by_alias is not None:
151
+ kwargs["by_alias"] = by_alias
145
152
  return model.model_dump(
146
153
  mode=mode,
147
154
  exclude=exclude,
@@ -149,7 +156,7 @@ def model_dump(
149
156
  exclude_defaults=exclude_defaults,
150
157
  # warnings are not supported in Pydantic v1
151
158
  warnings=True if PYDANTIC_V1 else warnings,
152
- by_alias=by_alias,
159
+ **kwargs,
153
160
  )
154
161
  return cast(
155
162
  "dict[str, Any]",
@@ -101,7 +101,10 @@ class Querystring:
101
101
  items.extend(self._stringify_item(key, item, opts))
102
102
  return items
103
103
  elif array_format == "indices":
104
- raise NotImplementedError("The array indices format is not supported yet")
104
+ items = []
105
+ for i, item in enumerate(value):
106
+ items.extend(self._stringify_item(f"{key}[{i}]", item, opts))
107
+ return items
105
108
  elif array_format == "brackets":
106
109
  items = []
107
110
  key = key + "[]"
@@ -1,3 +1,4 @@
1
+ from ._path import path_template as path_template
1
2
  from ._sync import asyncify as asyncify
2
3
  from ._proxy import LazyProxy as LazyProxy
3
4
  from ._utils import (
@@ -0,0 +1,127 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from typing import (
5
+ Any,
6
+ Mapping,
7
+ Callable,
8
+ )
9
+ from urllib.parse import quote
10
+
11
+ # Matches '.' or '..' where each dot is either literal or percent-encoded (%2e / %2E).
12
+ _DOT_SEGMENT_RE = re.compile(r"^(?:\.|%2[eE]){1,2}$")
13
+
14
+ _PLACEHOLDER_RE = re.compile(r"\{(\w+)\}")
15
+
16
+
17
+ def _quote_path_segment_part(value: str) -> str:
18
+ """Percent-encode `value` for use in a URI path segment.
19
+
20
+ Considers characters not in `pchar` set from RFC 3986 §3.3 to be unsafe.
21
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
22
+ """
23
+ # quote() already treats unreserved characters (letters, digits, and -._~)
24
+ # as safe, so we only need to add sub-delims, ':', and '@'.
25
+ # Notably, unlike the default `safe` for quote(), / is unsafe and must be quoted.
26
+ return quote(value, safe="!$&'()*+,;=:@")
27
+
28
+
29
+ def _quote_query_part(value: str) -> str:
30
+ """Percent-encode `value` for use in a URI query string.
31
+
32
+ Considers &, = and characters not in `query` set from RFC 3986 §3.4 to be unsafe.
33
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.4
34
+ """
35
+ return quote(value, safe="!$'()*+,;:@/?")
36
+
37
+
38
+ def _quote_fragment_part(value: str) -> str:
39
+ """Percent-encode `value` for use in a URI fragment.
40
+
41
+ Considers characters not in `fragment` set from RFC 3986 §3.5 to be unsafe.
42
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.5
43
+ """
44
+ return quote(value, safe="!$&'()*+,;=:@/?")
45
+
46
+
47
+ def _interpolate(
48
+ template: str,
49
+ values: Mapping[str, Any],
50
+ quoter: Callable[[str], str],
51
+ ) -> str:
52
+ """Replace {name} placeholders in `template`, quoting each value with `quoter`.
53
+
54
+ Placeholder names are looked up in `values`.
55
+
56
+ Raises:
57
+ KeyError: If a placeholder is not found in `values`.
58
+ """
59
+ # re.split with a capturing group returns alternating
60
+ # [text, name, text, name, ..., text] elements.
61
+ parts = _PLACEHOLDER_RE.split(template)
62
+
63
+ for i in range(1, len(parts), 2):
64
+ name = parts[i]
65
+ if name not in values:
66
+ raise KeyError(f"a value for placeholder {{{name}}} was not provided")
67
+ val = values[name]
68
+ if val is None:
69
+ parts[i] = "null"
70
+ elif isinstance(val, bool):
71
+ parts[i] = "true" if val else "false"
72
+ else:
73
+ parts[i] = quoter(str(values[name]))
74
+
75
+ return "".join(parts)
76
+
77
+
78
+ def path_template(template: str, /, **kwargs: Any) -> str:
79
+ """Interpolate {name} placeholders in `template` from keyword arguments.
80
+
81
+ Args:
82
+ template: The template string containing {name} placeholders.
83
+ **kwargs: Keyword arguments to interpolate into the template.
84
+
85
+ Returns:
86
+ The template with placeholders interpolated and percent-encoded.
87
+
88
+ Safe characters for percent-encoding are dependent on the URI component.
89
+ Placeholders in path and fragment portions are percent-encoded where the `segment`
90
+ and `fragment` sets from RFC 3986 respectively are considered safe.
91
+ Placeholders in the query portion are percent-encoded where the `query` set from
92
+ RFC 3986 §3.3 is considered safe except for = and & characters.
93
+
94
+ Raises:
95
+ KeyError: If a placeholder is not found in `kwargs`.
96
+ ValueError: If resulting path contains /./ or /../ segments (including percent-encoded dot-segments).
97
+ """
98
+ # Split the template into path, query, and fragment portions.
99
+ fragment_template: str | None = None
100
+ query_template: str | None = None
101
+
102
+ rest = template
103
+ if "#" in rest:
104
+ rest, fragment_template = rest.split("#", 1)
105
+ if "?" in rest:
106
+ rest, query_template = rest.split("?", 1)
107
+ path_template = rest
108
+
109
+ # Interpolate each portion with the appropriate quoting rules.
110
+ path_result = _interpolate(path_template, kwargs, _quote_path_segment_part)
111
+
112
+ # Reject dot-segments (. and ..) in the final assembled path. The check
113
+ # runs after interpolation so that adjacent placeholders or a mix of static
114
+ # text and placeholders that together form a dot-segment are caught.
115
+ # Also reject percent-encoded dot-segments to protect against incorrectly
116
+ # implemented normalization in servers/proxies.
117
+ for segment in path_result.split("/"):
118
+ if _DOT_SEGMENT_RE.match(segment):
119
+ raise ValueError(f"Constructed path {path_result!r} contains dot-segment {segment!r} which is not allowed")
120
+
121
+ result = path_result
122
+ if query_template is not None:
123
+ result += "?" + _interpolate(query_template, kwargs, _quote_query_part)
124
+ if fragment_template is not None:
125
+ result += "#" + _interpolate(fragment_template, kwargs, _quote_fragment_part)
126
+
127
+ return result
@@ -86,8 +86,9 @@ def _extract_items(
86
86
  index += 1
87
87
  if is_dict(obj):
88
88
  try:
89
- # We are at the last entry in the path so we must remove the field
90
- if (len(path)) == index:
89
+ # Remove the field if there are no more dict keys in the path,
90
+ # only "<array>" traversal markers or end.
91
+ if all(p == "<array>" for p in path[index:]):
91
92
  item = obj.pop(key)
92
93
  else:
93
94
  item = obj[key]
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "hiddenlayer"
4
- __version__ = "3.5.0" # x-release-please-version
4
+ __version__ = "3.6.0" # x-release-please-version
@@ -1,9 +1,13 @@
1
1
  # Custom extensions for HiddenLayer SDK
2
+ from ._beta import BetaWarning, warn_beta, check_beta_endpoint
2
3
  from .model_scan import ModelScanner, AsyncModelScanner
3
4
  from .community_scan import CommunityScanner, CommunityScanSource, AsyncCommunityScanner
4
5
  from .evaluation_sessions import EvaluationSessionsResource, AsyncEvaluationSessionsResource
5
6
 
6
7
  __all__ = [
8
+ "BetaWarning",
9
+ "warn_beta",
10
+ "check_beta_endpoint",
7
11
  "CommunityScanner",
8
12
  "AsyncCommunityScanner",
9
13
  "ModelScanner",
@@ -0,0 +1,45 @@
1
+ """Runtime beta warning utility.
2
+
3
+ Emits a warning when a beta endpoint is called, so SDK consumers know
4
+ the method is not yet GA.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import warnings
10
+
11
+
12
+ class BetaWarning(UserWarning):
13
+ """Warning emitted when a beta API endpoint is called."""
14
+
15
+
16
+ def warn_beta(qualified_name: str, *, stacklevel: int = 3) -> None:
17
+ """Emit a warning that a beta endpoint was called.
18
+
19
+ Args:
20
+ qualified_name: Fully qualified method name, e.g. "InteractionsResource.analyze"
21
+ stacklevel: How many frames to skip when reporting the warning location.
22
+ """
23
+ warnings.warn(
24
+ f"[BETA] {qualified_name}: This endpoint is not GA or Production ready "
25
+ "and is subject to changes at any time. Breaking changes may occur.",
26
+ BetaWarning,
27
+ stacklevel=stacklevel,
28
+ )
29
+
30
+
31
+ def check_beta_endpoint(url: str) -> None:
32
+ """Check whether *url* is a beta endpoint and emit a warning if so.
33
+
34
+ Args:
35
+ url: The URL path for the request (e.g. "/detection/v2/request-evaluations").
36
+ """
37
+ from ._beta_endpoints import BETA_ENDPOINTS
38
+
39
+ qualified_name = BETA_ENDPOINTS.get(url)
40
+ if qualified_name is not None:
41
+ # Called from _prepare_options, which is deeper in the stack than
42
+ # a direct warn_beta call from a resource method. The higher
43
+ # stacklevel won't point at user code, but the message itself
44
+ # identifies the method.
45
+ warn_beta(qualified_name, stacklevel=4)
@@ -0,0 +1,11 @@
1
+ """Auto-generated registry of beta endpoints.
2
+
3
+ DO NOT EDIT -- regenerated by scripts/utils/generate-beta-endpoints.cjs
4
+
5
+ Maps URL paths to qualified method names for runtime warnings.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ BETA_ENDPOINTS: dict[str, str] = {
10
+ "/evaluations/v1/red-team": "RedTeamResource.create",
11
+ }
@@ -9,7 +9,14 @@ import logging
9
9
  from typing import Union, Literal, cast
10
10
  from typing_extensions import TYPE_CHECKING
11
11
 
12
- from .scan_utils import get_scan_results, wait_for_scan_results, get_scan_results_async, wait_for_scan_results_async
12
+ from .scan_utils import (
13
+ ScanResultMixin,
14
+ AsyncScanResultMixin,
15
+ get_scan_results,
16
+ wait_for_scan_results,
17
+ get_scan_results_async,
18
+ wait_for_scan_results_async,
19
+ )
13
20
 
14
21
  logger = logging.getLogger(__name__)
15
22
 
@@ -31,7 +38,7 @@ class CommunityScanSource:
31
38
  HUGGING_FACE = "HUGGING_FACE"
32
39
 
33
40
 
34
- class CommunityScanner:
41
+ class CommunityScanner(ScanResultMixin):
35
42
  """
36
43
  Community scanner that provides the community_scan method with polling functionality.
37
44
 
@@ -108,7 +115,7 @@ class CommunityScanner:
108
115
  return get_scan_results(self._client, scan_id=scan_id)
109
116
 
110
117
 
111
- class AsyncCommunityScanner:
118
+ class AsyncCommunityScanner(AsyncScanResultMixin):
112
119
  """
113
120
  Async version of CommunityScanner for use with AsyncHiddenLayer client.
114
121
  """
@@ -171,4 +178,4 @@ class AsyncCommunityScanner:
171
178
  return await wait_for_scan_results_async(self._client, scan_id=scan_id)
172
179
  else:
173
180
  # Return current scan status without waiting
174
- return await get_scan_results_async(self._client, scan_id=scan_id)
181
+ return await get_scan_results_async(self._client, scan_id=scan_id)
@@ -12,7 +12,14 @@ from fnmatch import fnmatch
12
12
  from pathlib import Path
13
13
  from typing_extensions import TYPE_CHECKING
14
14
 
15
- from .scan_utils import get_scan_results, wait_for_scan_results, get_scan_results_async, wait_for_scan_results_async
15
+ from .scan_utils import (
16
+ ScanResultMixin,
17
+ AsyncScanResultMixin,
18
+ get_scan_results,
19
+ wait_for_scan_results,
20
+ get_scan_results_async,
21
+ wait_for_scan_results_async,
22
+ )
16
23
  from .._exceptions import BadRequestError
17
24
 
18
25
  logger = logging.getLogger(__name__)
@@ -114,7 +121,7 @@ def filter_path_objects(
114
121
 
115
122
  yield item
116
123
 
117
- class ModelScanner:
124
+ class ModelScanner(ScanResultMixin):
118
125
  """
119
126
  Model scanner that provides file and folder scanning functionality.
120
127
 
@@ -483,7 +490,7 @@ class ModelScanner:
483
490
  self._client.scans.upload.file.complete(file_id=upload.upload_id, scan_id=scan_id)
484
491
 
485
492
 
486
- class AsyncModelScanner:
493
+ class AsyncModelScanner(AsyncScanResultMixin):
487
494
  """
488
495
  Async version of ModelScanner for use with AsyncHiddenLayer client.
489
496
  """