splunk-soar-sdk 3.2.0__tar.gz → 3.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/PKG-INFO +1 -1
  2. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/app_structure/src_app.rst +1 -1
  3. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/pyproject.toml +1 -1
  4. splunk_soar_sdk-3.2.2/release_notes.txt +23 -0
  5. splunk_soar_sdk-3.2.2/release_version.txt +1 -0
  6. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/manifests/processors.py +23 -2
  7. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/dependencies.py +76 -18
  8. splunk_soar_sdk-3.2.2/tests/cli/manifests/test_python_version_resolution.py +288 -0
  9. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/meta/test_dependencies.py +38 -0
  10. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/uv.lock +1 -1
  11. splunk_soar_sdk-3.2.0/release_notes.txt +0 -21
  12. splunk_soar_sdk-3.2.0/release_version.txt +0 -1
  13. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  14. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  15. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/pull_request_template.md +0 -0
  16. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/utils/github.js +0 -0
  17. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/utils/update_version.py +0 -0
  18. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/workflows/code_quality.yml +0 -0
  19. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/workflows/commit_hygiene.yml +0 -0
  20. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/workflows/generate_docs.yml +0 -0
  21. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.github/workflows/semantic_release.yml +0 -0
  22. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.gitignore +0 -0
  23. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.pre-commit-config.yaml +0 -0
  24. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/.releaserc +0 -0
  25. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/LICENSE +0 -0
  26. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/README.md +0 -0
  27. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/commitlint.config.js +0 -0
  28. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/api_reference.rst +0 -0
  29. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/app_structure/index.rst +0 -0
  30. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/app_structure/pre-commit-config.yaml.rst +0 -0
  31. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/app_structure/pyproject.toml.rst +0 -0
  32. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/changelog.rst +0 -0
  33. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/cli_reference.rst +0 -0
  34. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/conf.py +0 -0
  35. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/custom_views/index.rst +0 -0
  36. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/custom_views/reusable_components.md +0 -0
  37. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/custom_views/templates.md +0 -0
  38. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/custom_views/view_handlers.md +0 -0
  39. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/getting_started/defining_asset.rst +0 -0
  40. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/getting_started/first_action.rst +0 -0
  41. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/getting_started/index.rst +0 -0
  42. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/getting_started/init_app.rst +0 -0
  43. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/getting_started/installation.rst +0 -0
  44. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/getting_started/testing_and_building.rst +0 -0
  45. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/docs/index.rst +0 -0
  46. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/__init__.py +0 -0
  47. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/abstract.py +0 -0
  48. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/action_results.py +0 -0
  49. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/actions_manager.py +0 -0
  50. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/apis/__init__.py +0 -0
  51. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/apis/artifact.py +0 -0
  52. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/apis/container.py +0 -0
  53. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/apis/utils.py +0 -0
  54. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/apis/vault.py +0 -0
  55. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app.py +0 -0
  56. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_cli_runner.py +0 -0
  57. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_client.py +0 -0
  58. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_templates/basic_app/.gitignore +0 -0
  59. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_templates/basic_app/.pre-commit-config.yaml +0 -0
  60. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_templates/basic_app/logo.svg +0 -0
  61. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_templates/basic_app/logo_dark.svg +0 -0
  62. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_templates/basic_app/src/__init__.py +0 -0
  63. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/app_templates/basic_app/uv.lock +0 -0
  64. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/asset.py +0 -0
  65. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/async_utils.py +0 -0
  66. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/__init__.py +0 -0
  67. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/cli.py +0 -0
  68. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/init/__init__.py +0 -0
  69. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/init/cli.py +0 -0
  70. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/manifests/__init__.py +0 -0
  71. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/manifests/cli.py +0 -0
  72. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/manifests/deserializers.py +0 -0
  73. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/manifests/serializers.py +0 -0
  74. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/package/cli.py +0 -0
  75. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/package/utils.py +0 -0
  76. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/path_utils.py +0 -0
  77. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/cli/utils.py +0 -0
  78. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/__init__.py +0 -0
  79. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/action_renderer.py +0 -0
  80. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/app_renderer.py +0 -0
  81. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/asset_renderer.py +0 -0
  82. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/renderer.py +0 -0
  83. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/templates/pyproject.toml.jinja +0 -0
  84. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/code_renderers/toml_renderer.py +0 -0
  85. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/colors.py +0 -0
  86. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/compat.py +0 -0
  87. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/crypto.py +0 -0
  88. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/__init__.py +0 -0
  89. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/action.py +0 -0
  90. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/make_request.py +0 -0
  91. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/on_es_poll.py +0 -0
  92. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/on_poll.py +0 -0
  93. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/test_connectivity.py +0 -0
  94. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/view_handler.py +0 -0
  95. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/decorators/webhook.py +0 -0
  96. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/exceptions.py +0 -0
  97. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/field_utils.py +0 -0
  98. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/input_spec.py +0 -0
  99. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/logging.py +0 -0
  100. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/__init__.py +0 -0
  101. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/actions.py +0 -0
  102. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/adapters.py +0 -0
  103. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/app.py +0 -0
  104. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/datatypes.py +0 -0
  105. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/meta/webhooks.py +0 -0
  106. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/__init__.py +0 -0
  107. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/artifact.py +0 -0
  108. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/attachment_input.py +0 -0
  109. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/container.py +0 -0
  110. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/finding.py +0 -0
  111. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/vault_attachment.py +0 -0
  112. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/models/view.py +0 -0
  113. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/params.py +0 -0
  114. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/paths.py +0 -0
  115. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/py.typed +0 -0
  116. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/action_result.py +0 -0
  117. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/app.py +0 -0
  118. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/base_connector.py +0 -0
  119. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/connector_result.py +0 -0
  120. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/consts.py +0 -0
  121. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/encryption_helper.py +0 -0
  122. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/install_info.py +0 -0
  123. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/json_keys.py +0 -0
  124. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/ph_ipc.py +0 -0
  125. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom/vault.py +0 -0
  126. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom_common/app_interface/app_interface.py +0 -0
  127. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/shims/phantom_common/encryption/encryption_manager_factory.py +0 -0
  128. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/base/base_template.html +0 -0
  129. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/base/error.html +0 -0
  130. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/base/header.html +0 -0
  131. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/base/logo_header.html +0 -0
  132. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/components/pie_chart.html +0 -0
  133. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/widgets/widget_resize_snippet.html +0 -0
  134. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/templates/widgets/widget_template.html +0 -0
  135. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/types.py +0 -0
  136. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/__init__.py +0 -0
  137. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/component_registry.py +0 -0
  138. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/components/__init__.py +0 -0
  139. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/components/pie_chart.py +0 -0
  140. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/template_filters.py +0 -0
  141. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/template_renderer.py +0 -0
  142. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/views/view_parser.py +0 -0
  143. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/webhooks/__init__.py +0 -0
  144. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/webhooks/models.py +0 -0
  145. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/src/soar_sdk/webhooks/routing.py +0 -0
  146. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/test.png +0 -0
  147. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/test.txt +0 -0
  148. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/__init__.py +0 -0
  149. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/__init__.py +0 -0
  150. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/datapath_parse.py +0 -0
  151. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/manifests/__init__.py +0 -0
  152. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/manifests/test_processors.py +0 -0
  153. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_assets/converted_app/actions.py.txt +0 -0
  154. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_cli.py +0 -0
  155. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_convert_cli.py +0 -0
  156. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_deserializers.py +0 -0
  157. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_init_cli.py +0 -0
  158. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_manifests_cli.py +0 -0
  159. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_package_cli.py +0 -0
  160. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_serializers.py +0 -0
  161. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/cli/test_utils.py +0 -0
  162. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/code_renderers/test_action_renderer.py +0 -0
  163. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/conftest.py +0 -0
  164. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/app.json +0 -0
  165. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/example_asset.json +0 -0
  166. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/logo.svg +0 -0
  167. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/logo_dark.svg +0 -0
  168. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/pyproject.toml +0 -0
  169. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/release_notes/v1.md +0 -0
  170. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/__init__.py +0 -0
  171. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/actions/__init__.py +0 -0
  172. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/actions/async_action.py +0 -0
  173. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/actions/generate_category.py +0 -0
  174. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/actions/reverse_string.py +0 -0
  175. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/app.py +0 -0
  176. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/src/ignoreme.txt +0 -0
  177. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/templates/reverse_string.html +0 -0
  178. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app/uv.lock +0 -0
  179. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/app.json +0 -0
  180. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/logo.svg +0 -0
  181. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/logo_dark.svg +0 -0
  182. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/pyproject.toml +0 -0
  183. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/src/__init__.py +0 -0
  184. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/src/app.py +0 -0
  185. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/example_app_with_webhook/uv.lock +0 -0
  186. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/interfaces/__init__.py +0 -0
  187. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/interfaces/test_artifact_interface.py +0 -0
  188. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/interfaces/test_container_interface.py +0 -0
  189. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/interfaces/test_vault_interface.py +0 -0
  190. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/meta/__init__.py +0 -0
  191. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/meta/test_actions.py +0 -0
  192. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/meta/test_adapters.py +0 -0
  193. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/meta/test_datatypes.py +0 -0
  194. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/meta/test_webhooks.py +0 -0
  195. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/mocks/__init__.py +0 -0
  196. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/mocks/dynamic_mocks.py +0 -0
  197. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/mocks/importable_action.py +0 -0
  198. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/stubs.py +0 -0
  199. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_action_results.py +0 -0
  200. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_actions_manager.py +0 -0
  201. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_app.py +0 -0
  202. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_app_action.py +0 -0
  203. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_app_action_params.py +0 -0
  204. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_app_action_results.py +0 -0
  205. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_app_client.py +0 -0
  206. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_app_runner.py +0 -0
  207. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_asset.py +0 -0
  208. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_assets/splunk-sdk-2.1.0.tar.gz +0 -0
  209. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_async_integration.py +0 -0
  210. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_async_utils.py +0 -0
  211. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_attachment_input.py +0 -0
  212. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_code_renderers.py +0 -0
  213. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_compat.py +0 -0
  214. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_container.py +0 -0
  215. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_custom_views.py +0 -0
  216. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_encryption.py +0 -0
  217. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_es_on_poll.py +0 -0
  218. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_field_utils.py +0 -0
  219. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_finding.py +0 -0
  220. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_input_spec.py +0 -0
  221. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_logging.py +0 -0
  222. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_make_request_action.py +0 -0
  223. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_on_poll.py +0 -0
  224. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_params.py +0 -0
  225. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_template_filters.py +0 -0
  226. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_template_renderer.py +0 -0
  227. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_test_connectivity.py +0 -0
  228. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/test_view_parser.py +0 -0
  229. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/webhooks/test_models.py +0 -0
  230. {splunk_soar_sdk-3.2.0 → splunk_soar_sdk-3.2.2}/tests/webhooks/test_routing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: splunk-soar-sdk
3
- Version: 3.2.0
3
+ Version: 3.2.2
4
4
  Summary: The official framework for developing and testing Splunk SOAR Apps
5
5
  Project-URL: Homepage, https://github.com/phantomcyber/splunk-soar-sdk
6
6
  Project-URL: Documentation, https://github.com/phantomcyber/splunk-soar-sdk
@@ -203,7 +203,7 @@ A successful ``test connectivity`` action should return ``None``, and a failure
203
203
  :lineno-match:
204
204
  :pyobject: on_poll
205
205
 
206
- ``on poll`` is another special action that apps may choose to implement. This action always takes an :class:`~soar_sdk.params.OnPollParams` instance as its parameter. If defined, this action will be called in order to ingest new data into the Splunk Splunk SOAR platform. The action should yield :class:`~soar_sdk.models.container.Container` and/or :class:`~soar_sdk.models.artifact.Artifact` instances representing the new data to be ingested. The SDK will handle actually creating the containers and artifacts in the platform.
206
+ ``on poll`` is another special action that apps may choose to implement. This action always takes an :class:`~soar_sdk.params.OnPollParams` instance as its parameter. If defined, this action will be called in order to ingest new data into the Splunk SOAR platform. The action should yield :class:`~soar_sdk.models.container.Container` and/or :class:`~soar_sdk.models.artifact.Artifact` instances representing the new data to be ingested. The SDK will handle actually creating the containers and artifacts in the platform.
207
207
 
208
208
  Make Request Action
209
209
  ^^^^^^^^^^^^^^
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "splunk-soar-sdk"
3
- version = "3.2.0"
3
+ version = "3.2.2"
4
4
  description = "The official framework for developing and testing Splunk SOAR Apps"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13, <=3.14"
@@ -0,0 +1,23 @@
1
+ ## [3.2.2](https://github.com/phantomcyber/splunk-soar-sdk/compare/3.2.1...3.2.2) (2025-11-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add dedent for multi-line strings and import ([a6c9799](https://github.com/phantomcyber/splunk-soar-sdk/commit/a6c97996ecf9ab0658d58b5d3d88d96500766f4e))
7
+ * fix dependency resolution when specifying a specific python version ([ac00bc7](https://github.com/phantomcyber/splunk-soar-sdk/commit/ac00bc778bcccd0bea9744795a893b7fd403553f))
8
+
9
+
10
+
11
+
12
+
13
+ ## [3.2.2](https://github.com/phantomcyber/splunk-soar-sdk/compare/3.2.1...3.2.2) (2025-11-19)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * add dedent for multi-line strings and import ([a6c9799](https://github.com/phantomcyber/splunk-soar-sdk/commit/a6c97996ecf9ab0658d58b5d3d88d96500766f4e))
19
+ * fix dependency resolution when specifying a specific python version ([ac00bc7](https://github.com/phantomcyber/splunk-soar-sdk/commit/ac00bc778bcccd0bea9744795a893b7fd403553f))
20
+
21
+
22
+
23
+
@@ -0,0 +1 @@
1
+ 3.2.2
@@ -5,9 +5,11 @@ from datetime import datetime, UTC
5
5
  from pathlib import Path
6
6
  from pprint import pprint
7
7
 
8
+ from packaging.specifiers import SpecifierSet
9
+
8
10
  from soar_sdk.app import App
9
11
  from soar_sdk.cli.path_utils import context_directory
10
- from soar_sdk.compat import UPDATE_TIME_FORMAT
12
+ from soar_sdk.compat import UPDATE_TIME_FORMAT, PythonVersion
11
13
  from soar_sdk.meta.adapters import TOMLDataAdapter
12
14
  from soar_sdk.meta.app import AppMeta
13
15
  from soar_sdk.meta.dependencies import UvLock
@@ -24,6 +26,22 @@ class ManifestProcessor:
24
26
  self.manifest_path = manifest_path
25
27
  self.project_context = Path(project_context)
26
28
 
29
+ def get_target_python_versions(self) -> list[str]:
30
+ """Get the intersection of project requires-python and SDK-supported versions."""
31
+ sdk_versions = [str(v) for v in PythonVersion.all()]
32
+
33
+ with open(self.project_context / "pyproject.toml") as f:
34
+ requires_python = toml.load(f).get("project", {}).get("requires-python", "")
35
+
36
+ if not requires_python:
37
+ return sdk_versions
38
+
39
+ # Use packaging.specifiers to check version compatibility
40
+ specifier_set = SpecifierSet(requires_python)
41
+ compatible = [version for version in sdk_versions if version in specifier_set]
42
+
43
+ return compatible
44
+
27
45
  def build(self, is_sdk_locally_built: bool = False) -> AppMeta:
28
46
  """Builds full AppMeta information including actions and other extra fields."""
29
47
  app_meta: AppMeta = self.load_toml_app_meta()
@@ -41,8 +59,11 @@ class ManifestProcessor:
41
59
  dep for dep in dependencies if dep.name != "splunk-soar-sdk"
42
60
  ]
43
61
 
62
+ # Get target Python versions from requires-python constraint
63
+ target_python_versions = self.get_target_python_versions()
64
+
44
65
  app_meta.pip313_dependencies, app_meta.pip314_dependencies = (
45
- uv_lock.resolve_dependencies(dependencies)
66
+ uv_lock.resolve_dependencies(dependencies, target_python_versions)
46
67
  )
47
68
 
48
69
  if app.webhook_meta is not None:
@@ -277,9 +277,7 @@ class UvPackage(BaseModel):
277
277
  for abi in abi_precedence:
278
278
  abi_wheels = [wheel for wheel in self.wheels if abi in wheel.abi_tags]
279
279
  for python in python_precedence:
280
- python_wheels = [
281
- wheel for wheel in abi_wheels if python in wheel.python_tags
282
- ]
280
+ python_wheels = self._filter_python_wheels(abi_wheels, python, abi)
283
281
  for platform in platform_precedence:
284
282
  platform_wheels = [
285
283
  wheel
@@ -293,6 +291,54 @@ class UvPackage(BaseModel):
293
291
  f"Could not find a suitable wheel for {self.name=}, {self.version=}, {abi_precedence=}, {python_precedence=}, {platform_precedence=}"
294
292
  )
295
293
 
294
+ def _filter_python_wheels(
295
+ self, wheels: list[UvWheel], target_python: str, abi: str
296
+ ) -> list[UvWheel]:
297
+ """Filter and sort wheels by Python version compatibility.
298
+
299
+ For abi3 wheels, prefers the highest compatible minimum version
300
+ (e.g., cp311-abi3 over cp38-abi3 for Python 3.13).
301
+ """
302
+ compatible = [
303
+ wheel
304
+ for wheel in wheels
305
+ if self._is_python_compatible(wheel, target_python, abi)
306
+ ]
307
+
308
+ # For abi3 wheels, prefer highest minimum version (closest to target)
309
+ if abi == "abi3" and compatible:
310
+ compatible = sorted(
311
+ compatible,
312
+ key=lambda w: max(
313
+ (int(tag[2:]) for tag in w.python_tags if tag.startswith("cp")),
314
+ default=0,
315
+ ),
316
+ reverse=True,
317
+ )
318
+
319
+ return compatible
320
+
321
+ def _is_python_compatible(
322
+ self, wheel: UvWheel, target_python: str, abi: str
323
+ ) -> bool:
324
+ """Check if a wheel is compatible with the target Python version.
325
+
326
+ For abi3 wheels, the Python tag indicates minimum version (e.g., cp311-abi3 works with Python ≥3.11).
327
+ For non-abi3 wheels, exact tag matching is required.
328
+ """
329
+ if target_python in wheel.python_tags:
330
+ return True
331
+
332
+ # For abi3 wheels, check if target >= minimum version (e.g., cp313 >= cp311)
333
+ if abi == "abi3":
334
+ return any(
335
+ int(tag[2:]) <= int(target_python[2:])
336
+ for tag in wheel.python_tags
337
+ if tag.startswith("cp") and target_python.startswith("cp")
338
+ )
339
+
340
+ return False
341
+
296
342
  _manylinux_precedence: ClassVar[list[str]] = [
297
343
  "_2_28", # glibc 2.28, latest stable version, supports Ubuntu 18.10+ and RHEL/Oracle 8+
298
344
  "_2_17", # glibc 2.17, LTS-ish, supports Ubuntu 13.10+ and RHEL/Oracle 7+
@@ -450,23 +496,35 @@ class UvLock(BaseModel):
450
496
  @staticmethod
451
497
  def resolve_dependencies(
452
498
  packages: list[UvPackage],
499
+ python_versions: list[str] | None = None,
453
500
  ) -> tuple[DependencyList, DependencyList]:
454
- """Resolve the dependencies for the given packages."""
455
- py313_wheels: list[DependencyWheel] = []
456
- py314_wheels: list[DependencyWheel] = []
501
+ """Resolve the dependencies for the given packages.
502
+
503
+ Args:
504
+ packages: List of packages to resolve dependencies for.
505
+ python_versions: List of Python versions to resolve for (e.g., ["3.13", "3.14"]).
506
+ If None, defaults to ["3.13", "3.14"] for backwards compatibility.
507
+
508
+ Returns:
509
+ Tuple of (py313_dependencies, py314_dependencies).
510
+ """
511
+ python_versions = python_versions or ["3.13", "3.14"]
512
+ resolve_both = len(python_versions) == 2
513
+
514
+ py313_wheels, py314_wheels = [], []
457
515
 
458
516
  for package in packages:
459
- wheel_313 = package.resolve_py313()
460
- wheel_314 = package.resolve_py314()
461
-
462
- if wheel_313 == wheel_314:
463
- wheel_313.add_platform_prefix("shared")
464
- wheel_314.add_platform_prefix("shared")
465
- else:
466
- wheel_313.add_platform_prefix("python313")
467
- wheel_314.add_platform_prefix("python314")
468
-
469
- py313_wheels.append(wheel_313)
470
- py314_wheels.append(wheel_314)
517
+ wheel_313 = package.resolve_py313() if "3.13" in python_versions else None
518
+ wheel_314 = package.resolve_py314() if "3.14" in python_versions else None
519
+
520
+ prefix = "shared" if not resolve_both or wheel_313 == wheel_314 else None
521
+
522
+ if wheel_313:
523
+ wheel_313.add_platform_prefix(prefix or "python313")
524
+ py313_wheels.append(wheel_313)
525
+
526
+ if wheel_314:
527
+ wheel_314.add_platform_prefix(prefix or "python314")
528
+ py314_wheels.append(wheel_314)
471
529
 
472
530
  return DependencyList(wheel=py313_wheels), DependencyList(wheel=py314_wheels)
@@ -0,0 +1,288 @@
1
+ import textwrap
2
+ import pytest
3
+ from unittest import mock
4
+
5
+ from soar_sdk.cli.manifests.processors import ManifestProcessor
6
+
7
+
8
+ class TestGetTargetPythonVersions:
9
+ """Test the get_target_python_versions method that determines which Python versions to build for."""
10
+
11
+ @pytest.fixture
12
+ def mock_pyproject_toml(self, tmp_path):
13
+ """Create a temporary directory for test pyproject.toml files."""
14
+ return tmp_path
15
+
16
+ def test_both_versions_when_no_constraint(self, mock_pyproject_toml):
17
+ """When no requires-python is specified, should return all SDK-supported versions."""
18
+ pyproject_content = textwrap.dedent(
19
+ """
20
+ [project]
21
+ name = "test-app"
22
+ version = "1.0.0"
23
+ """
24
+ )
25
+ (mock_pyproject_toml / "pyproject.toml").write_text(pyproject_content)
26
+
27
+ processor = ManifestProcessor(
28
+ "manifest.json", project_context=str(mock_pyproject_toml)
29
+ )
30
+ versions = processor.get_target_python_versions()
31
+
32
+ assert versions == ["3.13", "3.14"]
33
+
34
+ def test_only_313_when_constrained(self, mock_pyproject_toml):
35
+ """When requires-python excludes 3.14, should return only 3.13."""
36
+ pyproject_content = textwrap.dedent(
37
+ """
38
+ [project]
39
+ name = "test-app"
40
+ version = "1.0.0"
41
+ requires-python = ">=3.13, <3.14"
42
+ """
43
+ )
44
+ (mock_pyproject_toml / "pyproject.toml").write_text(pyproject_content)
45
+
46
+ processor = ManifestProcessor(
47
+ "manifest.json", project_context=str(mock_pyproject_toml)
48
+ )
49
+ versions = processor.get_target_python_versions()
50
+
51
+ assert versions == ["3.13"]
52
+
53
+ def test_only_314_when_constrained(self, mock_pyproject_toml):
54
+ """When requires-python excludes 3.13, should return only 3.14."""
55
+ pyproject_content = textwrap.dedent(
56
+ """
57
+ [project]
58
+ name = "test-app"
59
+ version = "1.0.0"
60
+ requires-python = ">=3.14"
61
+ """
62
+ )
63
+ (mock_pyproject_toml / "pyproject.toml").write_text(pyproject_content)
64
+
65
+ processor = ManifestProcessor(
66
+ "manifest.json", project_context=str(mock_pyproject_toml)
67
+ )
68
+ versions = processor.get_target_python_versions()
69
+
70
+ assert versions == ["3.14"]
71
+
72
+ def test_both_versions_with_inclusive_range(self, mock_pyproject_toml):
73
+ """When requires-python includes both 3.13 and 3.14, should return both."""
74
+ pyproject_content = textwrap.dedent(
75
+ """
76
+ [project]
77
+ name = "test-app"
78
+ version = "1.0.0"
79
+ requires-python = ">=3.13, <=3.14"
80
+ """
81
+ )
82
+ (mock_pyproject_toml / "pyproject.toml").write_text(pyproject_content)
83
+
84
+ processor = ManifestProcessor(
85
+ "manifest.json", project_context=str(mock_pyproject_toml)
86
+ )
87
+ versions = processor.get_target_python_versions()
88
+
89
+ assert versions == ["3.13", "3.14"]
90
+
91
+ def test_empty_when_no_match(self, mock_pyproject_toml):
92
+ """When requires-python doesn't match any SDK versions, should return empty."""
93
+ pyproject_content = textwrap.dedent(
94
+ """
95
+ [project]
96
+ name = "test-app"
97
+ version = "1.0.0"
98
+ requires-python = ">=3.15"
99
+ """
100
+ )
101
+ (mock_pyproject_toml / "pyproject.toml").write_text(pyproject_content)
102
+
103
+ processor = ManifestProcessor(
104
+ "manifest.json", project_context=str(mock_pyproject_toml)
105
+ )
106
+ versions = processor.get_target_python_versions()
107
+
108
+ assert versions == []
109
+
110
+
111
+ class TestResolveDependencies:
112
+ """Test the resolve_dependencies method that determines which wheels to include."""
113
+
114
+ @pytest.fixture
115
+ def mock_package(self):
116
+ """Create a mock package with resolve methods that return DependencyWheel objects."""
117
+ from soar_sdk.meta.dependencies import DependencyWheel, UvWheel
118
+
119
+ package = mock.Mock()
120
+
121
+ # Create proper DependencyWheel objects
122
+ wheel_313 = DependencyWheel(
123
+ module="test_package",
124
+ input_file="test_package-1.0.0-cp313-cp313-manylinux.whl",
125
+ wheel=UvWheel(
126
+ filename="test_package-1.0.0-cp313-cp313-manylinux.whl",
127
+ hash="sha256:abc123",
128
+ ),
129
+ )
130
+ wheel_314 = DependencyWheel(
131
+ module="test_package",
132
+ input_file="test_package-1.0.0-cp314-cp314-manylinux.whl",
133
+ wheel=UvWheel(
134
+ filename="test_package-1.0.0-cp314-cp314-manylinux.whl",
135
+ hash="sha256:def456",
136
+ ),
137
+ )
138
+
139
+ package.resolve_py313.return_value = wheel_313
140
+ package.resolve_py314.return_value = wheel_314
141
+
142
+ return package, wheel_313, wheel_314
143
+
144
+ def test_resolve_both_versions_by_default(self, mock_package):
145
+ """When no python_versions specified, should resolve both 3.13 and 3.14."""
146
+ from soar_sdk.meta.dependencies import UvLock
147
+
148
+ package, wheel_313, wheel_314 = mock_package
149
+
150
+ py313_deps, py314_deps = UvLock.resolve_dependencies([package])
151
+
152
+ package.resolve_py313.assert_called_once()
153
+ package.resolve_py314.assert_called_once()
154
+ assert len(py313_deps.wheel) == 1
155
+ assert len(py314_deps.wheel) == 1
156
+ # Should use version-specific prefixes since wheels are different
157
+ assert "python313" in py313_deps.wheel[0].input_file
158
+ assert "python314" in py314_deps.wheel[0].input_file
159
+
160
+ def test_resolve_only_313(self, mock_package):
161
+ """When python_versions=["3.13"], should only resolve 3.13."""
162
+ from soar_sdk.meta.dependencies import UvLock
163
+
164
+ package, wheel_313, wheel_314 = mock_package
165
+
166
+ py313_deps, py314_deps = UvLock.resolve_dependencies(
167
+ [package], python_versions=["3.13"]
168
+ )
169
+
170
+ package.resolve_py313.assert_called_once()
171
+ package.resolve_py314.assert_not_called()
172
+ assert len(py313_deps.wheel) == 1
173
+ assert len(py314_deps.wheel) == 0
174
+ # Should use shared prefix since only one version
175
+ assert "shared" in py313_deps.wheel[0].input_file
176
+
177
+ def test_resolve_only_314(self, mock_package):
178
+ """When python_versions=["3.14"], should only resolve 3.14."""
179
+ from soar_sdk.meta.dependencies import UvLock
180
+
181
+ package, wheel_313, wheel_314 = mock_package
182
+
183
+ py313_deps, py314_deps = UvLock.resolve_dependencies(
184
+ [package], python_versions=["3.14"]
185
+ )
186
+
187
+ package.resolve_py313.assert_not_called()
188
+ package.resolve_py314.assert_called_once()
189
+ assert len(py313_deps.wheel) == 0
190
+ assert len(py314_deps.wheel) == 1
191
+ # Should use shared prefix since only one version
192
+ assert "shared" in py314_deps.wheel[0].input_file
193
+
194
+ def test_shared_prefix_when_wheels_identical(self):
195
+ """When both versions resolve to identical wheels, should use 'shared' prefix."""
196
+ from soar_sdk.meta.dependencies import UvLock, DependencyWheel, UvWheel
197
+
198
+ package = mock.Mock()
199
+
200
+ # Create identical wheels
201
+ identical_wheel = DependencyWheel(
202
+ module="test_package",
203
+ input_file="test_package-1.0.0-py3-none-any.whl",
204
+ wheel=UvWheel(
205
+ filename="test_package-1.0.0-py3-none-any.whl",
206
+ hash="sha256:same",
207
+ ),
208
+ )
209
+
210
+ package.resolve_py313.return_value = identical_wheel
211
+ package.resolve_py314.return_value = identical_wheel
212
+
213
+ py313_deps, py314_deps = UvLock.resolve_dependencies(
214
+ [package], python_versions=["3.13", "3.14"]
215
+ )
216
+
217
+ # Both should use shared prefix
218
+ assert "shared" in py313_deps.wheel[0].input_file
219
+ assert "shared" in py314_deps.wheel[0].input_file
220
+
221
+ def test_version_specific_prefix_when_wheels_different(self, mock_package):
222
+ """When wheels differ between versions, should use version-specific prefixes."""
223
+ from soar_sdk.meta.dependencies import UvLock
224
+
225
+ package, wheel_313, wheel_314 = mock_package
226
+
227
+ py313_deps, py314_deps = UvLock.resolve_dependencies(
228
+ [package], python_versions=["3.13", "3.14"]
229
+ )
230
+
231
+ # Should use version-specific prefixes since wheels are different
232
+ assert "python313" in py313_deps.wheel[0].input_file
233
+ assert "python314" in py314_deps.wheel[0].input_file
234
+
235
+ def test_shared_prefix_when_only_one_version(self, mock_package):
236
+ """When only one version is requested, should use 'shared' prefix."""
237
+ from soar_sdk.meta.dependencies import UvLock
238
+
239
+ package, wheel_313, wheel_314 = mock_package
240
+
241
+ py313_deps, py314_deps = UvLock.resolve_dependencies(
242
+ [package], python_versions=["3.13"]
243
+ )
244
+
245
+ assert len(py313_deps.wheel) == 1
246
+ assert "shared" in py313_deps.wheel[0].input_file
247
+
248
+ def test_empty_list_for_unresolved_version(self, mock_package):
249
+ """When a version is not in python_versions, its dependency list should be empty."""
250
+ from soar_sdk.meta.dependencies import UvLock
251
+
252
+ package, wheel_313, wheel_314 = mock_package
253
+
254
+ # Only resolve 3.13
255
+ py313_deps, py314_deps = UvLock.resolve_dependencies(
256
+ [package], python_versions=["3.13"]
257
+ )
258
+
259
+ # 3.14 list should be empty
260
+ assert len(py314_deps.wheel) == 0
261
+ assert py314_deps.wheel == []
262
+
263
+
264
+ class TestIntegration:
265
+ """Integration tests for the complete workflow."""
266
+
267
+ def test_313_only_project_skips_314_resolution(self, tmp_path):
268
+ """Test that a project with requires-python='>=3.13, <3.14' doesn't try to resolve 3.14 wheels."""
269
+ pyproject_content = textwrap.dedent(
270
+ """
271
+ [project]
272
+ name = "test-app"
273
+ version = "1.0.0"
274
+ requires-python = ">=3.13, <3.14"
275
+ dependencies = ["httpx"]
276
+ """
277
+ )
278
+ (tmp_path / "pyproject.toml").write_text(pyproject_content)
279
+
280
+ processor = ManifestProcessor("manifest.json", project_context=str(tmp_path))
281
+ versions = processor.get_target_python_versions()
282
+
283
+ # Should only get 3.13
284
+ assert versions == ["3.13"]
285
+
286
+ # Verify this would be passed to resolve_dependencies
287
+ # (actual resolution would happen in build(), but we can verify the input)
288
+ assert "3.14" not in versions
@@ -136,6 +136,44 @@ class TestUvPackage:
136
136
  )
137
137
  assert wheel.basename == "certifi-2025.1.31-py3-none-any"
138
138
 
139
+ def test_find_wheel_abi3_compatibility(self):
140
+ """Test that abi3 wheels match correctly with newer Python versions.
141
+
142
+ abi3 wheels specify a minimum Python version. For example, cp311-abi3
143
+ means the wheel works with Python 3.11 and all later versions (3.12, 3.13, etc.).
144
+ """
145
+ package = UvPackage(
146
+ name="cryptography",
147
+ version="46.0.3",
148
+ dependencies=[],
149
+ wheels=[
150
+ # cp38-abi3 wheel: works with Python 3.8+
151
+ UvWheel(
152
+ url="https://notarealurl.com/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl",
153
+ hash="sha256:abc123",
154
+ size=1000000,
155
+ ),
156
+ # cp311-abi3 wheel: works with Python 3.11+
157
+ UvWheel(
158
+ url="https://notarealurl.com/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl",
159
+ hash="sha256:def456",
160
+ size=1000000,
161
+ ),
162
+ ],
163
+ )
164
+
165
+ # Python 3.13 should match both abi3 wheels since 3.13 >= 3.8 and 3.13 >= 3.11
166
+ # Should prefer cp311-abi3 (highest compatible minimum version)
167
+ wheel = package._find_wheel(
168
+ abi_precedence=["cp313", "abi3", "none"],
169
+ python_precedence=["cp313", "py3"],
170
+ platform_precedence=["manylinux_2_28_x86_64", "any"],
171
+ )
172
+
173
+ # Should match cp311-abi3 (prefer higher minimum version over cp38-abi3)
174
+ assert "abi3" in wheel.basename
175
+ assert wheel.basename == "cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64"
176
+
139
177
  def test_resolve_no_aarch64_available(self):
140
178
  package = UvPackage(
141
179
  name="mypy",
@@ -1131,7 +1131,7 @@ wheels = [
1131
1131
 
1132
1132
  [[package]]
1133
1133
  name = "splunk-soar-sdk"
1134
- version = "3.2.0"
1134
+ version = "3.2.2"
1135
1135
  source = { editable = "." }
1136
1136
  dependencies = [
1137
1137
  { name = "beautifulsoup4", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
@@ -1,21 +0,0 @@
1
- # [3.2.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/3.1.0...3.2.0) (2025-10-30)
2
-
3
-
4
- ### Features
5
-
6
- * add on_es_poll action type ([eddf792](https://github.com/phantomcyber/splunk-soar-sdk/commit/eddf79249a815b50b7d12da213f6736ba5047078))
7
-
8
-
9
-
10
-
11
-
12
- # [3.2.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/3.1.0...3.2.0) (2025-10-30)
13
-
14
-
15
- ### Features
16
-
17
- * add on_es_poll action type ([eddf792](https://github.com/phantomcyber/splunk-soar-sdk/commit/eddf79249a815b50b7d12da213f6736ba5047078))
18
-
19
-
20
-
21
-
@@ -1 +0,0 @@
1
- 3.2.0
File without changes