splunk-soar-sdk 2.2.0__tar.gz → 2.3.1__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 (220) hide show
  1. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/PKG-INFO +1 -1
  2. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/pyproject.toml +1 -1
  3. splunk_soar_sdk-2.3.1/release_notes.txt +23 -0
  4. splunk_soar_sdk-2.3.1/release_version.txt +1 -0
  5. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/abstract.py +1 -1
  6. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/action_results.py +12 -17
  7. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app.py +2 -7
  8. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_client.py +2 -2
  9. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/manifests/serializers.py +17 -3
  10. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/make_request.py +17 -5
  11. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/params.py +35 -2
  12. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_serializers.py +82 -2
  13. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/app.json +23 -6
  14. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/app.py +10 -8
  15. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_action_results.py +1 -11
  16. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_actions_manager.py +6 -18
  17. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_make_request_action.py +17 -2
  18. splunk_soar_sdk-2.3.1/tests/test_params.py +43 -0
  19. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/uv.lock +1 -1
  20. splunk_soar_sdk-2.2.0/release_notes.txt +0 -21
  21. splunk_soar_sdk-2.2.0/release_version.txt +0 -1
  22. splunk_soar_sdk-2.2.0/tests/test_params.py +0 -21
  23. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  24. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  25. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/pull_request_template.md +0 -0
  26. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/utils/github.js +0 -0
  27. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/utils/update_version.py +0 -0
  28. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/workflows/code_quality.yml +0 -0
  29. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/workflows/commit_hygiene.yml +0 -0
  30. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/workflows/generate_docs.yml +0 -0
  31. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.github/workflows/semantic_release.yml +0 -0
  32. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.gitignore +0 -0
  33. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.pre-commit-config.yaml +0 -0
  34. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/.releaserc +0 -0
  35. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/LICENSE +0 -0
  36. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/README.md +0 -0
  37. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/commitlint.config.js +0 -0
  38. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/api_reference.rst +0 -0
  39. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/app_structure/index.rst +0 -0
  40. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/app_structure/pre-commit-config.yaml.rst +0 -0
  41. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/app_structure/pyproject.toml.rst +0 -0
  42. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/app_structure/src_app.rst +0 -0
  43. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/changelog.rst +0 -0
  44. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/cli_reference.rst +0 -0
  45. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/conf.py +0 -0
  46. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/custom_views/index.rst +0 -0
  47. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/custom_views/reusable_components.md +0 -0
  48. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/custom_views/templates.md +0 -0
  49. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/custom_views/view_handlers.md +0 -0
  50. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/getting_started/defining_asset.rst +0 -0
  51. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/getting_started/first_action.rst +0 -0
  52. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/getting_started/index.rst +0 -0
  53. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/getting_started/init_app.rst +0 -0
  54. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/getting_started/installation.rst +0 -0
  55. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/getting_started/testing_and_building.rst +0 -0
  56. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/docs/index.rst +0 -0
  57. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/__init__.py +0 -0
  58. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/actions_manager.py +0 -0
  59. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/apis/__init__.py +0 -0
  60. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/apis/artifact.py +0 -0
  61. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/apis/container.py +0 -0
  62. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/apis/utils.py +0 -0
  63. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/apis/vault.py +0 -0
  64. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_cli_runner.py +0 -0
  65. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_templates/basic_app/.gitignore +0 -0
  66. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_templates/basic_app/.pre-commit-config.yaml +0 -0
  67. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_templates/basic_app/logo.svg +0 -0
  68. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_templates/basic_app/logo_dark.svg +0 -0
  69. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_templates/basic_app/src/__init__.py +0 -0
  70. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/app_templates/basic_app/uv.lock +0 -0
  71. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/asset.py +0 -0
  72. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/async_utils.py +0 -0
  73. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/__init__.py +0 -0
  74. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/cli.py +0 -0
  75. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/init/__init__.py +0 -0
  76. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/init/cli.py +0 -0
  77. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/manifests/__init__.py +0 -0
  78. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/manifests/cli.py +0 -0
  79. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/manifests/deserializers.py +0 -0
  80. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/manifests/processors.py +0 -0
  81. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/package/cli.py +0 -0
  82. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/package/utils.py +0 -0
  83. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/path_utils.py +0 -0
  84. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/cli/utils.py +0 -0
  85. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/__init__.py +0 -0
  86. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/action_renderer.py +0 -0
  87. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/app_renderer.py +0 -0
  88. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/asset_renderer.py +0 -0
  89. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/renderer.py +0 -0
  90. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/templates/pyproject.toml.jinja +0 -0
  91. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/code_renderers/toml_renderer.py +0 -0
  92. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/colors.py +0 -0
  93. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/compat.py +0 -0
  94. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/crypto.py +0 -0
  95. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/__init__.py +0 -0
  96. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/action.py +0 -0
  97. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/on_poll.py +0 -0
  98. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/test_connectivity.py +0 -0
  99. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/view_handler.py +0 -0
  100. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/decorators/webhook.py +0 -0
  101. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/exceptions.py +0 -0
  102. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/input_spec.py +0 -0
  103. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/logging.py +0 -0
  104. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/__init__.py +0 -0
  105. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/actions.py +0 -0
  106. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/adapters.py +0 -0
  107. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/app.py +0 -0
  108. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/datatypes.py +0 -0
  109. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/dependencies.py +0 -0
  110. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/meta/webhooks.py +0 -0
  111. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/models/__init__.py +0 -0
  112. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/models/artifact.py +0 -0
  113. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/models/container.py +0 -0
  114. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/models/vault_attachment.py +0 -0
  115. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/models/view.py +0 -0
  116. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/paths.py +0 -0
  117. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/py.typed +0 -0
  118. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/action_result.py +0 -0
  119. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/app.py +0 -0
  120. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/base_connector.py +0 -0
  121. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/connector_result.py +0 -0
  122. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/consts.py +0 -0
  123. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/encryption_helper.py +0 -0
  124. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/install_info.py +0 -0
  125. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/json_keys.py +0 -0
  126. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/ph_ipc.py +0 -0
  127. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom/vault.py +0 -0
  128. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom_common/app_interface/app_interface.py +0 -0
  129. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/shims/phantom_common/encryption/encryption_manager_factory.py +0 -0
  130. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/base/base_template.html +0 -0
  131. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/base/error.html +0 -0
  132. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/base/header.html +0 -0
  133. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/base/logo_header.html +0 -0
  134. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/components/pie_chart.html +0 -0
  135. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/widgets/widget_resize_snippet.html +0 -0
  136. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/templates/widgets/widget_template.html +0 -0
  137. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/types.py +0 -0
  138. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/__init__.py +0 -0
  139. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/component_registry.py +0 -0
  140. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/components/__init__.py +0 -0
  141. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/components/pie_chart.py +0 -0
  142. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/template_filters.py +0 -0
  143. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/template_renderer.py +0 -0
  144. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/views/view_parser.py +0 -0
  145. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/webhooks/__init__.py +0 -0
  146. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/webhooks/models.py +0 -0
  147. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/src/soar_sdk/webhooks/routing.py +0 -0
  148. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/test.png +0 -0
  149. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/test.txt +0 -0
  150. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/__init__.py +0 -0
  151. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/__init__.py +0 -0
  152. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/datapath_parse.py +0 -0
  153. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/manifests/__init__.py +0 -0
  154. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/manifests/test_processors.py +0 -0
  155. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_assets/converted_app/actions.py.txt +0 -0
  156. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_cli.py +0 -0
  157. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_convert_cli.py +0 -0
  158. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_deserializers.py +0 -0
  159. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_init_cli.py +0 -0
  160. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_manifests_cli.py +0 -0
  161. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_package_cli.py +0 -0
  162. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/cli/test_utils.py +0 -0
  163. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/code_renderers/test_action_renderer.py +0 -0
  164. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/conftest.py +0 -0
  165. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/example_asset.json +0 -0
  166. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/logo.svg +0 -0
  167. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/logo_dark.svg +0 -0
  168. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/pyproject.toml +0 -0
  169. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/__init__.py +0 -0
  170. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/actions/__init__.py +0 -0
  171. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/actions/async_action.py +0 -0
  172. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/actions/generate_category.py +0 -0
  173. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/actions/reverse_string.py +0 -0
  174. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/src/ignoreme.txt +0 -0
  175. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/templates/reverse_string.html +0 -0
  176. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app/uv.lock +0 -0
  177. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/app.json +0 -0
  178. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/logo.svg +0 -0
  179. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/logo_dark.svg +0 -0
  180. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/pyproject.toml +0 -0
  181. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/src/__init__.py +0 -0
  182. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/src/app.py +0 -0
  183. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/example_app_with_webhook/uv.lock +0 -0
  184. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/interfaces/__init__.py +0 -0
  185. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/interfaces/test_artifact_interface.py +0 -0
  186. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/interfaces/test_container_interface.py +0 -0
  187. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/interfaces/test_vault_interface.py +0 -0
  188. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/meta/__init__.py +0 -0
  189. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/meta/test_actions.py +0 -0
  190. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/meta/test_adapters.py +0 -0
  191. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/meta/test_datatypes.py +0 -0
  192. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/meta/test_dependencies.py +0 -0
  193. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/meta/test_webhooks.py +0 -0
  194. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/mocks/__init__.py +0 -0
  195. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/mocks/dynamic_mocks.py +0 -0
  196. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/mocks/importable_action.py +0 -0
  197. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/stubs.py +0 -0
  198. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_app.py +0 -0
  199. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_app_action.py +0 -0
  200. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_app_action_params.py +0 -0
  201. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_app_action_results.py +0 -0
  202. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_app_client.py +0 -0
  203. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_app_runner.py +0 -0
  204. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_asset.py +0 -0
  205. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_assets/splunk-sdk-2.1.0.tar.gz +0 -0
  206. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_async_integration.py +0 -0
  207. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_async_utils.py +0 -0
  208. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_code_renderers.py +0 -0
  209. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_compat.py +0 -0
  210. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_container.py +0 -0
  211. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_custom_views.py +0 -0
  212. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_encryption.py +0 -0
  213. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_logging.py +0 -0
  214. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_on_poll.py +0 -0
  215. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_template_filters.py +0 -0
  216. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_template_renderer.py +0 -0
  217. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_test_connectivity.py +0 -0
  218. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/test_view_parser.py +0 -0
  219. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/tests/webhooks/test_models.py +0 -0
  220. {splunk_soar_sdk-2.2.0 → splunk_soar_sdk-2.3.1}/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: 2.2.0
3
+ Version: 2.3.1
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "splunk-soar-sdk"
3
- version = "2.2.0"
3
+ version = "2.3.1"
4
4
  description = "The official framework for developing and testing Splunk SOAR Apps"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9, <3.14"
@@ -0,0 +1,23 @@
1
+ ## [2.3.1](https://github.com/phantomcyber/splunk-soar-sdk/compare/2.3.0...2.3.1) (2025-10-07)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * make request changes ([ae80851](https://github.com/phantomcyber/splunk-soar-sdk/commit/ae8085161210157c9d83aa296642c4c682803805))
7
+ * pass empty messages to platform instead of setting dummy message ([133b7f5](https://github.com/phantomcyber/splunk-soar-sdk/commit/133b7f5ace4e782469633a40ded03f54bb605d0d))
8
+
9
+
10
+
11
+
12
+
13
+ ## [2.3.1](https://github.com/phantomcyber/splunk-soar-sdk/compare/2.3.0...2.3.1) (2025-10-07)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * make request changes ([ae80851](https://github.com/phantomcyber/splunk-soar-sdk/commit/ae8085161210157c9d83aa296642c4c682803805))
19
+ * pass empty messages to platform instead of setting dummy message ([133b7f5](https://github.com/phantomcyber/splunk-soar-sdk/commit/133b7f5ace4e782469633a40ded03f54bb605d0d))
20
+
21
+
22
+
23
+
@@ -0,0 +1 @@
1
+ 2.3.1
@@ -234,6 +234,6 @@ class SOARClient(Generic[SummaryType]):
234
234
  pass
235
235
 
236
236
  @abstractmethod
237
- def get_message(self) -> Optional[str]:
237
+ def get_message(self) -> str:
238
238
  """Get the summary message for the action run."""
239
239
  pass
@@ -2,10 +2,10 @@ from typing import Optional, Union, get_origin, get_args, Any
2
2
  from collections.abc import Iterator
3
3
  from typing_extensions import NotRequired, TypedDict
4
4
  from pydantic import BaseModel, Field
5
+ import itertools
5
6
 
6
7
  from soar_sdk.compat import remove_when_soar_newer_than
7
8
  from soar_sdk.shims.phantom.action_result import ActionResult as PhantomActionResult
8
-
9
9
  from soar_sdk.meta.datatypes import as_datatype
10
10
 
11
11
  remove_when_soar_newer_than(
@@ -92,7 +92,6 @@ def OutputField(
92
92
  example_values: Optional[list[Union[str, float, bool]]] = None,
93
93
  alias: Optional[str] = None,
94
94
  column_name: Optional[str] = None,
95
- column_order: Optional[int] = None,
96
95
  ) -> Any: # noqa: ANN401
97
96
  """Define metadata for an action output field.
98
97
 
@@ -107,7 +106,6 @@ def OutputField(
107
106
  in documentation and for testing/validation purposes.
108
107
  alias: Optional alternative name for the field when serialized.
109
108
  column_name: Optional name for the field when displayed in a table.
110
- column_order: Optional order for the field when displayed in a table (0-indexed).
111
109
 
112
110
  Note:
113
111
  Column name and order must be set together, if one is set but the other is not, an error will be raised.
@@ -128,7 +126,6 @@ def OutputField(
128
126
  alias=alias,
129
127
  cef_types=cef_types,
130
128
  column_name=column_name,
131
- column_order=column_order,
132
129
  )
133
130
 
134
131
 
@@ -163,7 +160,9 @@ class ActionOutput(BaseModel):
163
160
 
164
161
  @classmethod
165
162
  def _to_json_schema(
166
- cls, parent_datapath: str = "action_result.data.*"
163
+ cls,
164
+ parent_datapath: str = "action_result.data.*",
165
+ column_order_counter: Optional[itertools.count] = None,
167
166
  ) -> Iterator[OutputFieldSpecification]:
168
167
  """Convert the ActionOutput class to SOAR-compatible JSON schema.
169
168
 
@@ -174,6 +173,8 @@ class ActionOutput(BaseModel):
174
173
  Args:
175
174
  parent_datapath: The base datapath for fields in this output.
176
175
  Defaults to "action_result.data.*" for top-level outputs.
176
+ column_order_counter: Iterator for tracking column order across fields.
177
+ Used internally to maintain sequential column ordering. Defaults to itertools.count().
177
178
 
178
179
  Yields:
179
180
  OutputFieldSpecification objects describing each field in the schema.
@@ -187,6 +188,9 @@ class ActionOutput(BaseModel):
187
188
  Nested ActionOutput classes are recursively processed.
188
189
  Boolean fields automatically get [True, False] example values.
189
190
  """
191
+ if column_order_counter is None:
192
+ column_order_counter = itertools.count()
193
+
190
194
  for _field_name, field in cls.__fields__.items():
191
195
  field_name = alias if (alias := field.alias) else _field_name
192
196
 
@@ -219,7 +223,7 @@ class ActionOutput(BaseModel):
219
223
 
220
224
  if issubclass(field_type, ActionOutput):
221
225
  # If the field is another ActionOutput, recursively call _to_json_schema
222
- yield from field_type._to_json_schema(datapath)
226
+ yield from field_type._to_json_schema(datapath, column_order_counter)
223
227
  continue
224
228
  else:
225
229
  try:
@@ -241,20 +245,11 @@ class ActionOutput(BaseModel):
241
245
  if field_type is bool:
242
246
  schema_field["example_values"] = [True, False]
243
247
 
244
- # Validate column metadata - both column_name and column_order must be present together
245
248
  column_name = field.field_info.extra.get("column_name")
246
- column_order = field.field_info.extra.get("column_order")
247
-
248
- # Check if exactly one is set (XOR condition - invalid)
249
- if (column_name is None) != (column_order is None):
250
- raise ValueError(
251
- f"Field '{field_name}' must have both 'column_name' and 'column_order' "
252
- f"or neither. Found: column_name={column_name}, column_order={column_order}"
253
- )
254
249
 
255
- if column_name is not None and column_order is not None:
250
+ if column_name is not None:
256
251
  schema_field["column_name"] = column_name
257
- schema_field["column_order"] = column_order
252
+ schema_field["column_order"] = next(column_order_counter)
258
253
 
259
254
  yield schema_field
260
255
 
@@ -636,7 +636,7 @@ class App:
636
636
  ],
637
637
  actions_manager: ActionsManager,
638
638
  action_params: Optional[Params] = None,
639
- message: Optional[str] = None,
639
+ message: str = "",
640
640
  summary: Optional[ActionOutput] = None,
641
641
  ) -> bool:
642
642
  """Handles multiple ways of returning response from action.
@@ -657,9 +657,7 @@ class App:
657
657
  )
658
658
  # Handle empty list/iterator case
659
659
  if not statuses:
660
- result = ActionOutput(
661
- status=True, message=message or "Action completed successfully"
662
- )
660
+ result = ActionOutput(status=True, message=message)
663
661
  else:
664
662
  return all(statuses)
665
663
 
@@ -667,9 +665,6 @@ class App:
667
665
  output_dict = result.dict(by_alias=True)
668
666
  param_dict = action_params.dict() if action_params else None
669
667
 
670
- if not message:
671
- message = "Action completed successfully"
672
-
673
668
  result = ActionResult(
674
669
  status=True,
675
670
  message=message,
@@ -44,7 +44,7 @@ class AppClient(SOARClient[SummaryType]):
44
44
  self.basic_auth: Optional[BasicAuth] = None
45
45
 
46
46
  self._summary: Optional[SummaryType] = None
47
- self._message: Optional[str] = None
47
+ self._message: str = ""
48
48
  self.__container_id: int = 0
49
49
  self.__asset_id: str = ""
50
50
 
@@ -171,6 +171,6 @@ class AppClient(SOARClient[SummaryType]):
171
171
  """Get the summary for the action result."""
172
172
  return self._summary
173
173
 
174
- def get_message(self) -> Optional[str]:
174
+ def get_message(self) -> str:
175
175
  """Get the message for the action result."""
176
176
  return self._message
@@ -1,6 +1,7 @@
1
1
  from typing import Any, Optional
2
2
  from collections.abc import Iterator
3
3
  from logging import getLogger
4
+ import itertools
4
5
 
5
6
  from soar_sdk.meta.datatypes import as_datatype
6
7
  from soar_sdk.params import Params
@@ -29,8 +30,12 @@ class OutputsSerializer:
29
30
  @staticmethod
30
31
  def serialize_parameter_datapaths(
31
32
  params_class: type[Params],
33
+ column_order_counter: Optional[itertools.count] = None,
32
34
  ) -> Iterator[OutputFieldSpecification]:
33
35
  """Serializes the parameter data paths of a Params class to JSON schema."""
36
+ if column_order_counter is None:
37
+ column_order_counter = itertools.count()
38
+
34
39
  for field_name, field in params_class.__fields__.items():
35
40
  spec = OutputFieldSpecification(
36
41
  data_path=f"action_result.parameter.{field_name}",
@@ -38,6 +43,12 @@ class OutputsSerializer:
38
43
  )
39
44
  if cef_types := field.field_info.extra.get("cef_types"):
40
45
  spec["contains"] = cef_types
46
+
47
+ column_name = field.field_info.extra.get("column_name")
48
+
49
+ if column_name is not None:
50
+ spec["column_name"] = column_name
51
+ spec["column_order"] = next(column_order_counter)
41
52
  yield spec
42
53
 
43
54
  @classmethod
@@ -57,10 +68,13 @@ class OutputsSerializer:
57
68
  data_path="action_result.message",
58
69
  data_type="string",
59
70
  )
60
- params = cls.serialize_parameter_datapaths(params_class)
61
- outputs = outputs_class._to_json_schema()
71
+ column_order_counter = itertools.count()
72
+ params = cls.serialize_parameter_datapaths(params_class, column_order_counter)
73
+ outputs = outputs_class._to_json_schema(
74
+ column_order_counter=column_order_counter
75
+ )
62
76
  summary = (
63
- summary_class._to_json_schema("action_result.summary")
77
+ summary_class._to_json_schema("action_result.summary", column_order_counter)
64
78
  if summary_class
65
79
  else []
66
80
  )
@@ -43,19 +43,31 @@ class MakeRequestDecorator:
43
43
  "The 'make_request' decorator can only be used once per App instance."
44
44
  )
45
45
 
46
- # Validate function signature - must have at least one parameter of type MakeRequestParams
46
+ # Validate function signature - must have exactly one parameter of type MakeRequestParams
47
47
  signature = inspect.signature(function)
48
48
  params = list(signature.parameters.values())
49
49
 
50
- if not any(param.annotation == MakeRequestParams for param in params):
50
+ make_request_params = [
51
+ param
52
+ for param in params
53
+ if inspect.isclass(param.annotation)
54
+ and issubclass(param.annotation, MakeRequestParams)
55
+ ]
56
+
57
+ if len(make_request_params) == 0:
58
+ raise TypeError(
59
+ "Make request action function must have exactly one parameter of type MakeRequestParams or its subclass."
60
+ )
61
+ elif len(make_request_params) > 1:
62
+ param_names = [p.name for p in make_request_params]
51
63
  raise TypeError(
52
- f"Make request action function must have at least one parameter of type MakeRequestParams, got {params[0].annotation}"
64
+ f"Make request action function can only have one MakeRequestParams parameter, "
65
+ f"but found {len(make_request_params)}: {param_names}"
53
66
  )
54
67
 
55
68
  action_identifier = "make_request"
56
69
  action_name = "make request"
57
- # for make request action use MakeRequestParams
58
- validated_params_class = MakeRequestParams
70
+ validated_params_class = make_request_params[0].annotation
59
71
 
60
72
  return_type = inspect.signature(function).return_annotation
61
73
  if return_type is not inspect.Signature.empty:
@@ -1,4 +1,4 @@
1
- from typing import Optional, Union, Any
1
+ from typing import Optional, Union, Any, ClassVar
2
2
  from typing_extensions import NotRequired, TypedDict
3
3
 
4
4
  from pydantic.fields import Field, Undefined
@@ -22,6 +22,7 @@ def Param(
22
22
  allow_list: bool = False,
23
23
  sensitive: bool = False,
24
24
  alias: Optional[str] = None,
25
+ column_name: Optional[str] = None,
25
26
  ) -> Any: # noqa: ANN401
26
27
  """Representation of a single complex action parameter.
27
28
 
@@ -49,6 +50,7 @@ def Param(
49
50
  :param allow_list: Use this key to specify if the parameter supports specifying
50
51
  multiple values as a comma separated string.
51
52
  :param kwargs: additional kwargs accepted by pydantic.Field
53
+ :param column_name: Optional name for the parameter when displayed in an output table.
52
54
  :return: returns the FieldInfo object as pydantic.Field
53
55
  """
54
56
  if value_list is None:
@@ -64,6 +66,7 @@ def Param(
64
66
  allow_list=allow_list,
65
67
  sensitive=sensitive,
66
68
  alias=alias,
69
+ column_name=column_name,
67
70
  )
68
71
 
69
72
 
@@ -80,6 +83,8 @@ class InputFieldSpecification(TypedDict):
80
83
  value_list: NotRequired[list[str]]
81
84
  allow_list: bool
82
85
  default: NotRequired[Union[str, int, float, bool]]
86
+ column_name: NotRequired[str]
87
+ column_order: NotRequired[int]
83
88
 
84
89
 
85
90
  class Params(BaseModel):
@@ -173,6 +178,34 @@ class OnPollParams(Params):
173
178
  class MakeRequestParams(Params):
174
179
  """Canonical parameters for the special make request action."""
175
180
 
181
+ # Define allowed field names for subclasses
182
+ _ALLOWED_FIELDS: ClassVar[set[str]] = {
183
+ "http_method",
184
+ "endpoint",
185
+ "headers",
186
+ "query_parameters",
187
+ "body",
188
+ "timeout",
189
+ "verify_ssl",
190
+ }
191
+
192
+ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None:
193
+ """Validate that subclasses only define allowed fields."""
194
+ super().__init_subclass__(**kwargs)
195
+ cls._validate_make_request_fields()
196
+
197
+ @classmethod
198
+ def _validate_make_request_fields(cls) -> None:
199
+ """Ensure subclasses only define allowed MakeRequest fields."""
200
+ # Check if any fields are not in the allowed set
201
+ invalid_fields = set(cls.__fields__.keys()) - cls._ALLOWED_FIELDS
202
+
203
+ if invalid_fields:
204
+ raise TypeError(
205
+ f"MakeRequestParams subclass '{cls.__name__}' can only define these fields: "
206
+ f"{sorted(cls._ALLOWED_FIELDS)}. Invalid fields: {sorted(invalid_fields)}"
207
+ )
208
+
176
209
  http_method: str = Param(
177
210
  description="The HTTP method to use for the request.",
178
211
  required=True,
@@ -189,7 +222,7 @@ class MakeRequestParams(Params):
189
222
  required=False,
190
223
  )
191
224
 
192
- query_params: str = Param(
225
+ query_parameters: str = Param(
193
226
  description="The query string to send with the request.",
194
227
  required=False,
195
228
  )
@@ -153,7 +153,7 @@ def test_outputs_serialize_with_defaults():
153
153
 
154
154
  def test_outputs_serialize_output_class():
155
155
  class SampleNestedOutput(ActionOutput):
156
- bool_value: bool = OutputField(column_name="Nested Value", column_order=1)
156
+ bool_value: bool = OutputField(column_name="Nested Value")
157
157
 
158
158
  class SampleOutput(ActionOutput):
159
159
  string_value: str
@@ -163,7 +163,6 @@ def test_outputs_serialize_output_class():
163
163
  cef_types=["ip"],
164
164
  example_values=["1.1.1.1"],
165
165
  column_name="CEF Value",
166
- column_order=0,
167
166
  )
168
167
  nested_value: SampleNestedOutput
169
168
  underscored_value: str = OutputField(alias="_underscored_value")
@@ -306,3 +305,84 @@ def test_outputs_serialize_with_parameters_class():
306
305
  "example_values": [1],
307
306
  },
308
307
  ]
308
+
309
+
310
+ def test_serialize_parameter_datapaths():
311
+ class SampleParams(Params):
312
+ cef_value: str = Param(cef_types=["user name"], column_name="CEF Value")
313
+
314
+ serialized_parameter_datapaths = list(
315
+ OutputsSerializer.serialize_parameter_datapaths(SampleParams)
316
+ )
317
+
318
+ assert serialized_parameter_datapaths == [
319
+ {
320
+ "data_path": "action_result.parameter.cef_value",
321
+ "data_type": "string",
322
+ "contains": ["user name"],
323
+ "column_name": "CEF Value",
324
+ "column_order": 0,
325
+ },
326
+ ]
327
+
328
+
329
+ def test_serilized_datapaths_params():
330
+ class SampleParams(Params):
331
+ int_value: int
332
+ str_value: str
333
+ bool_value: bool
334
+ cef_value: str = Param(cef_types=["user name"], column_name="CEF Value")
335
+
336
+ class SampleOutput(ActionOutput):
337
+ string_value: str = OutputField(column_name="String Value")
338
+
339
+ serialized_outputs = OutputsSerializer.serialize_datapaths(
340
+ SampleParams, SampleOutput
341
+ )
342
+
343
+ assert serialized_outputs == [
344
+ {
345
+ "data_path": "action_result.status",
346
+ "data_type": "string",
347
+ "example_values": ["success", "failure"],
348
+ },
349
+ {
350
+ "data_path": "action_result.message",
351
+ "data_type": "string",
352
+ },
353
+ {
354
+ "data_path": "action_result.parameter.int_value",
355
+ "data_type": "numeric",
356
+ },
357
+ {
358
+ "data_path": "action_result.parameter.str_value",
359
+ "data_type": "string",
360
+ },
361
+ {
362
+ "data_path": "action_result.parameter.bool_value",
363
+ "data_type": "boolean",
364
+ },
365
+ {
366
+ "data_path": "action_result.parameter.cef_value",
367
+ "data_type": "string",
368
+ "contains": ["user name"],
369
+ "column_name": "CEF Value",
370
+ "column_order": 0,
371
+ },
372
+ {
373
+ "data_path": "action_result.data.*.string_value",
374
+ "data_type": "string",
375
+ "column_name": "String Value",
376
+ "column_order": 1,
377
+ },
378
+ {
379
+ "data_path": "summary.total_objects",
380
+ "data_type": "numeric",
381
+ "example_values": [1],
382
+ },
383
+ {
384
+ "data_path": "summary.total_objects_successful",
385
+ "data_type": "numeric",
386
+ "example_values": [1],
387
+ },
388
+ ]
@@ -246,7 +246,18 @@
246
246
  "read_only": true,
247
247
  "versions": "EQ(*)",
248
248
  "verbose": "",
249
- "parameters": {},
249
+ "parameters": {
250
+ "company_name": {
251
+ "order": 0,
252
+ "name": "company_name",
253
+ "description": "Company Name",
254
+ "data_type": "string",
255
+ "required": true,
256
+ "primary": false,
257
+ "allow_list": false,
258
+ "default": "Splunk"
259
+ }
260
+ },
250
261
  "output": [
251
262
  {
252
263
  "data_path": "action_result.status",
@@ -260,6 +271,12 @@
260
271
  "data_path": "action_result.message",
261
272
  "data_type": "string"
262
273
  },
274
+ {
275
+ "data_path": "action_result.parameter.company_name",
276
+ "data_type": "string",
277
+ "column_name": "Company Name",
278
+ "column_order": 0
279
+ },
263
280
  {
264
281
  "data_path": "action_result.data.*.name",
265
282
  "data_type": "string",
@@ -269,7 +286,7 @@
269
286
  "Jim"
270
287
  ],
271
288
  "column_name": "Name",
272
- "column_order": 0
289
+ "column_order": 1
273
290
  },
274
291
  {
275
292
  "data_path": "action_result.data.*.age",
@@ -280,7 +297,7 @@
280
297
  35
281
298
  ],
282
299
  "column_name": "Age",
283
- "column_order": 1
300
+ "column_order": 2
284
301
  },
285
302
  {
286
303
  "data_path": "summary.total_objects",
@@ -482,9 +499,9 @@
482
499
  "primary": false,
483
500
  "allow_list": false
484
501
  },
485
- "query_params": {
502
+ "query_parameters": {
486
503
  "order": 3,
487
- "name": "query_params",
504
+ "name": "query_parameters",
488
505
  "description": "The query string to send with the request.",
489
506
  "data_type": "string",
490
507
  "required": false,
@@ -545,7 +562,7 @@
545
562
  "data_type": "string"
546
563
  },
547
564
  {
548
- "data_path": "action_result.parameter.query_params",
565
+ "data_path": "action_result.parameter.query_parameters",
549
566
  "data_type": "string"
550
567
  },
551
568
  {
@@ -5,7 +5,7 @@ from zoneinfo import ZoneInfo
5
5
  from soar_sdk.abstract import SOARClient
6
6
  from soar_sdk.app import App
7
7
  from soar_sdk.asset import AssetField, BaseAsset
8
- from soar_sdk.params import OnPollParams, MakeRequestParams, Params
8
+ from soar_sdk.params import OnPollParams, MakeRequestParams, Params, Param
9
9
  from soar_sdk.models.container import Container
10
10
  from soar_sdk.models.artifact import Artifact
11
11
  from soar_sdk.action_results import ActionOutput, MakeRequestOutput, OutputField
@@ -73,12 +73,12 @@ def test_empty_list_output(
73
73
 
74
74
 
75
75
  class JsonOutput(ActionOutput):
76
- name: str = OutputField(
77
- example_values=["John", "Jane", "Jim"], column_name="Name", column_order=0
78
- )
79
- age: int = OutputField(
80
- example_values=[25, 30, 35], column_name="Age", column_order=1
81
- )
76
+ name: str = OutputField(example_values=["John", "Jane", "Jim"], column_name="Name")
77
+ age: int = OutputField(example_values=[25, 30, 35], column_name="Age")
78
+
79
+
80
+ class TableParams(Params):
81
+ company_name: str = Param(column_name="Company Name", default="Splunk")
82
82
 
83
83
 
84
84
  @app.action(render_as="json")
@@ -87,7 +87,9 @@ def test_json_output(params: Params, asset: Asset, soar: SOARClient) -> JsonOutp
87
87
 
88
88
 
89
89
  @app.action(render_as="table")
90
- def test_table_output(params: Params, asset: Asset, soar: SOARClient) -> JsonOutput:
90
+ def test_table_output(
91
+ params: TableParams, asset: Asset, soar: SOARClient
92
+ ) -> JsonOutput:
91
93
  return JsonOutput(name="John", age=25)
92
94
 
93
95
 
@@ -157,7 +157,7 @@ def test_action_output_to_dict():
157
157
 
158
158
  def test_action_output_to_json_schema_with_column_name_and_column_order():
159
159
  class ExampleActionOutputWithColumnNames(ActionOutput):
160
- stringy_field: str = OutputField(column_name="Stringy Field", column_order=0)
160
+ stringy_field: str = OutputField(column_name="Stringy Field")
161
161
 
162
162
  schema = list(ExampleActionOutputWithColumnNames._to_json_schema())
163
163
  assert schema == [
@@ -168,13 +168,3 @@ def test_action_output_to_json_schema_with_column_name_and_column_order():
168
168
  "column_order": 0,
169
169
  }
170
170
  ]
171
-
172
-
173
- def test_action_output_to_json_schema_with_column_name_and_column_order_missing():
174
- class ExampleActionOutputWithColumnNames(ActionOutput):
175
- stringy_field: str = OutputField(column_name="Stringy Field")
176
-
177
- with pytest.raises(
178
- ValueError, match="must have both 'column_name' and 'column_order'"
179
- ):
180
- list(ExampleActionOutputWithColumnNames._to_json_schema())
@@ -98,10 +98,7 @@ def test_action_called_returning_iterator(
98
98
  example_app.handle(simple_action_input.json())
99
99
 
100
100
  assert len(example_app.actions_manager.get_results()) == 5
101
- assert all(
102
- "success" in result.message
103
- for result in example_app.actions_manager.get_results()
104
- )
101
+ assert all(result.status for result in example_app.actions_manager.get_results())
105
102
 
106
103
 
107
104
  def test_async_action_called_returning_iterator(
@@ -120,10 +117,7 @@ def test_async_action_called_returning_iterator(
120
117
  example_app.handle(simple_action_input.json())
121
118
 
122
119
  assert len(example_app.actions_manager.get_results()) == 5
123
- assert all(
124
- "success" in result.message
125
- for result in example_app.actions_manager.get_results()
126
- )
120
+ assert all(result.status for result in example_app.actions_manager.get_results())
127
121
 
128
122
 
129
123
  def test_action_called_returning_list(
@@ -139,10 +133,7 @@ def test_action_called_returning_list(
139
133
  example_app.handle(simple_action_input.json())
140
134
 
141
135
  assert len(example_app.actions_manager.get_results()) == 5
142
- assert all(
143
- "success" in result.message
144
- for result in example_app.actions_manager.get_results()
145
- )
136
+ assert all(result.status for result in example_app.actions_manager.get_results())
146
137
 
147
138
 
148
139
  def test_async_action_called_returning_list(
@@ -158,10 +149,7 @@ def test_async_action_called_returning_list(
158
149
  example_app.handle(simple_action_input.json())
159
150
 
160
151
  assert len(example_app.actions_manager.get_results()) == 5
161
- assert all(
162
- "success" in result.message
163
- for result in example_app.actions_manager.get_results()
164
- )
152
+ assert all(result.status for result in example_app.actions_manager.get_results())
165
153
 
166
154
 
167
155
  def test_action_called_with_default_message_set(
@@ -174,7 +162,7 @@ def test_action_called_with_default_message_set(
174
162
  example_app.handle(simple_action_input.json())
175
163
 
176
164
  assert len(example_app.actions_manager.get_results()) == 1
177
- assert "success" in example_app.actions_manager.get_results()[0].message
165
+ assert example_app.actions_manager.get_results()[0].status
178
166
 
179
167
 
180
168
  def test_action_called_with_timezone_asset(example_app: App):
@@ -204,7 +192,7 @@ def test_action_called_with_timezone_asset(example_app: App):
204
192
  example_app.handle(action_input.json())
205
193
 
206
194
  assert len(example_app.actions_manager.get_results()) == 1
207
- assert "success" in example_app.actions_manager.get_results()[0].message
195
+ assert example_app.actions_manager.get_results()[0].status
208
196
 
209
197
 
210
198
  def test_actions_provider_running_undefined_action(