salesforce-data-customcode 6.1.0.dev6__tar.gz → 6.1.0.dev7__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 (129) hide show
  1. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/PKG-INFO +1 -1
  2. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/pyproject.toml +1 -1
  3. salesforce_data_customcode-6.1.0.dev7/src/datacustomcode/named_credential/direct/auth.py +191 -0
  4. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/credentials.py +1 -0
  5. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/external_callout/README.md +5 -1
  6. salesforce_data_customcode-6.1.0.dev6/src/datacustomcode/named_credential/direct/auth.py +0 -63
  7. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/LICENSE.txt +0 -0
  8. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/README.md +0 -0
  9. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/__init__.py +0 -0
  10. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/auth.py +0 -0
  11. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/cli.py +0 -0
  12. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/client.py +0 -0
  13. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/cmd.py +0 -0
  14. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/common_config.py +0 -0
  15. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/config.py +0 -0
  16. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/config.yaml +0 -0
  17. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/constants.py +0 -0
  18. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/credentials.py +0 -0
  19. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/deploy.py +0 -0
  20. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_platform_client.py +0 -0
  21. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_platform_config.py +0 -0
  22. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/__init__.py +0 -0
  23. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/base.py +0 -0
  24. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/errors.py +0 -0
  25. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/impl/default.py +0 -0
  26. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/spark_base.py +0 -0
  27. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/spark_default.py +0 -0
  28. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/types.py +0 -0
  29. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions_config.py +0 -0
  30. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/__init__.py +0 -0
  31. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/base.py +0 -0
  32. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/path/__init__.py +0 -0
  33. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/path/default.py +0 -0
  34. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/__init__.py +0 -0
  35. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/base.py +0 -0
  36. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/feature_types/__init__.py +0 -0
  37. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/feature_types/chunking.py +0 -0
  38. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/runtime.py +0 -0
  39. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function_utils.py +0 -0
  40. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/__init__.py +0 -0
  41. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/base.py +0 -0
  42. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/__init__.py +0 -0
  43. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/base.py +0 -0
  44. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/query_api.py +0 -0
  45. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/sf_cli.py +0 -0
  46. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/utils.py +0 -0
  47. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/__init__.py +0 -0
  48. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/base.py +0 -0
  49. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/csv.py +0 -0
  50. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/print.py +0 -0
  51. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/__init__.py +0 -0
  52. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/base.py +0 -0
  53. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/default.py +0 -0
  54. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/errors.py +0 -0
  55. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/spark_base.py +0 -0
  56. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/spark_default.py +0 -0
  57. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/__init__.py +0 -0
  58. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_request.py +0 -0
  59. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_request_builder.py +0 -0
  60. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_response.py +0 -0
  61. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_response_builder.py +0 -0
  62. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway_config.py +0 -0
  63. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/mixin.py +0 -0
  64. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/__init__.py +0 -0
  65. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/base.py +0 -0
  66. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/default.py +0 -0
  67. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/__init__.py +0 -0
  68. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/transport.py +0 -0
  69. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/url_resolver.py +0 -0
  70. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/errors.py +0 -0
  71. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/spark_base.py +0 -0
  72. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/spark_default.py +0 -0
  73. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/__init__.py +0 -0
  74. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_method.py +0 -0
  75. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_request.py +0 -0
  76. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_request_builder.py +0 -0
  77. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_response.py +0 -0
  78. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_response_builder.py +0 -0
  79. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential_config.py +0 -0
  80. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/py.typed +0 -0
  81. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/run.py +0 -0
  82. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/scan.py +0 -0
  83. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/spark/__init__.py +0 -0
  84. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/spark/base.py +0 -0
  85. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/spark/default.py +0 -0
  86. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/template.py +0 -0
  87. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/__init__.py +0 -0
  88. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/.devcontainer/devcontainer.json +0 -0
  89. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/Dockerfile.dependencies +0 -0
  90. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/README.md +0 -0
  91. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/build_native_dependencies.sh +0 -0
  92. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/chunking/payload/config.json +0 -0
  93. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/chunking/payload/entrypoint.py +0 -0
  94. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/chunking/requirements.txt +0 -0
  95. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/README.md +0 -0
  96. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/config.json +0 -0
  97. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/entrypoint.py +0 -0
  98. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/external_callout_config.json +0 -0
  99. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/tests/test.json +0 -0
  100. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/config.json +0 -0
  101. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/entrypoint.py +0 -0
  102. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/files/chunking_prompt.txt +0 -0
  103. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/tests/test.json +0 -0
  104. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_prediction/config.json +0 -0
  105. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_prediction/entrypoint.py +0 -0
  106. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_prediction/tests/test.json +0 -0
  107. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/payload/config.json +0 -0
  108. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/payload/entrypoint.py +0 -0
  109. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/payload/utility.py +0 -0
  110. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/requirements-dev.txt +0 -0
  111. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/requirements.txt +0 -0
  112. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/.devcontainer/devcontainer.json +0 -0
  113. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/Dockerfile +0 -0
  114. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/Dockerfile.dependencies +0 -0
  115. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/README.md +0 -0
  116. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/account.ipynb +0 -0
  117. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/build_native_dependencies.sh +0 -0
  118. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/employee_hierarchy/employee_data.csv +0 -0
  119. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/employee_hierarchy/entrypoint.py +0 -0
  120. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/external_callout/entrypoint.py +0 -0
  121. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/external_callout/external_callout_config.json +0 -0
  122. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/streaming_deltas/entrypoint.py +0 -0
  123. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/jupyterlab.sh +0 -0
  124. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/payload/config.json +0 -0
  125. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/payload/entrypoint.py +0 -0
  126. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/requirements-dev.txt +0 -0
  127. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/requirements.txt +0 -0
  128. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/token_provider.py +0 -0
  129. {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: salesforce-data-customcode
3
- Version: 6.1.0.dev6
3
+ Version: 6.1.0.dev7
4
4
  Summary: Data Cloud Custom Code SDK
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE.txt
@@ -18,7 +18,7 @@ license = "Apache-2.0"
18
18
  name = "salesforce-data-customcode"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.10,<3.12"
21
- version = "6.1.0.dev6"
21
+ version = "6.1.0.dev7"
22
22
 
23
23
  [tool.black]
24
24
  exclude = '''
@@ -0,0 +1,191 @@
1
+ # Copyright (c) 2025, Salesforce, Inc.
2
+ # SPDX-License-Identifier: Apache-2
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """
16
+ Inject external credential auth into an outgoing request.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import base64
22
+ import datetime
23
+ import hashlib
24
+ import hmac
25
+ from typing import (
26
+ TYPE_CHECKING,
27
+ Any,
28
+ Dict,
29
+ )
30
+ import urllib.parse
31
+
32
+ from requests.auth import AuthBase
33
+
34
+ from datacustomcode.named_credential.direct.credentials import AuthType
35
+
36
+ if TYPE_CHECKING:
37
+ from requests.models import PreparedRequest
38
+
39
+ _SIGV4_ALGORITHM = "AWS4-HMAC-SHA256"
40
+
41
+
42
+ class DynamicAuthHandler(AuthBase):
43
+ def __init__(self, cred_config: Dict[str, Any]) -> None:
44
+ self.config = cred_config
45
+ self.auth_type = cred_config.get("auth_type")
46
+
47
+ def __call__(self, request: PreparedRequest) -> PreparedRequest:
48
+ if self.auth_type == AuthType.BASIC.value:
49
+ user = self.config.get("username", "")
50
+ pwd = self.config.get("password", "")
51
+ token = base64.b64encode(f"{user}:{pwd}".encode()).decode()
52
+ request.headers["Authorization"] = f"Basic {token}"
53
+
54
+ elif self.auth_type == AuthType.CUSTOM.value:
55
+ for name, value in self.config.get("custom_headers", {}).items():
56
+ request.headers[name] = value
57
+
58
+ elif self.auth_type in (AuthType.OAUTH.value, AuthType.JWT.value):
59
+ bearer = self.config.get("access_token") or self.config.get("token")
60
+ if not bearer:
61
+ raise ValueError(
62
+ f"'{self.auth_type}' auth requires an 'access_token' or 'token'."
63
+ )
64
+ request.headers["Authorization"] = f"Bearer {bearer}"
65
+
66
+ elif self.auth_type == AuthType.AWS_SIG_V4.value:
67
+ self._sign_aws_sigv4(request)
68
+
69
+ else:
70
+ raise ValueError(f"Unsupported auth_type '{self.auth_type}'.")
71
+
72
+ return request
73
+
74
+ def _sign_aws_sigv4(self, request: PreparedRequest) -> None:
75
+ """Sign ``request`` with AWS Signature Version 4.
76
+
77
+ Requires ``aws_access_key_id``, ``aws_secret_access_key``, ``aws_region``,
78
+ and ``aws_service`` in the credential config; ``aws_session_token`` is
79
+ optional (for temporary credentials). The signed date, payload hash, and
80
+ (when present) session token are added as ``x-amz-*`` headers so the sent
81
+ request matches what was signed.
82
+ """
83
+ access_key = self.config.get("aws_access_key_id")
84
+ secret_key = self.config.get("aws_secret_access_key")
85
+ region = self.config.get("aws_region")
86
+ service = self.config.get("aws_service")
87
+ session_token = self.config.get("aws_session_token")
88
+ missing = [
89
+ name
90
+ for name, value in (
91
+ ("aws_access_key_id", access_key),
92
+ ("aws_secret_access_key", secret_key),
93
+ ("aws_region", region),
94
+ ("aws_service", service),
95
+ )
96
+ if not value
97
+ ]
98
+ if missing:
99
+ raise ValueError(f"'{self.auth_type}' auth requires {', '.join(missing)}.")
100
+ access_key = str(access_key)
101
+ secret_key = str(secret_key)
102
+ region = str(region)
103
+ service = str(service)
104
+
105
+ parsed = urllib.parse.urlsplit(str(request.url or ""))
106
+ host = parsed.netloc
107
+ canonical_uri = urllib.parse.quote(parsed.path or "/", safe="/-_.~")
108
+ canonical_query = _canonical_query_string(parsed.query)
109
+
110
+ body = request.body or b""
111
+ if isinstance(body, str):
112
+ body = body.encode("utf-8")
113
+ payload_hash = hashlib.sha256(body).hexdigest()
114
+
115
+ now = datetime.datetime.now(datetime.timezone.utc)
116
+ amz_date = now.strftime("%Y%m%dT%H%M%SZ")
117
+ datestamp = now.strftime("%Y%m%d")
118
+
119
+ request.headers["x-amz-date"] = amz_date
120
+ request.headers["x-amz-content-sha256"] = payload_hash
121
+ if session_token:
122
+ request.headers["x-amz-security-token"] = session_token
123
+
124
+ signed = {
125
+ "host": host,
126
+ "x-amz-content-sha256": payload_hash,
127
+ "x-amz-date": amz_date,
128
+ }
129
+ if session_token:
130
+ signed["x-amz-security-token"] = session_token
131
+ signed_headers = ";".join(sorted(signed))
132
+ canonical_headers = "".join(
133
+ f"{name}:{signed[name]}\n" for name in sorted(signed)
134
+ )
135
+
136
+ canonical_request = "\n".join(
137
+ [
138
+ request.method or "GET",
139
+ canonical_uri,
140
+ canonical_query,
141
+ canonical_headers,
142
+ signed_headers,
143
+ payload_hash,
144
+ ]
145
+ )
146
+ credential_scope = f"{datestamp}/{region}/{service}/aws4_request"
147
+ string_to_sign = "\n".join(
148
+ [
149
+ _SIGV4_ALGORITHM,
150
+ amz_date,
151
+ credential_scope,
152
+ hashlib.sha256(canonical_request.encode("utf-8")).hexdigest(),
153
+ ]
154
+ )
155
+ signing_key = _derive_signing_key(secret_key, datestamp, region, service)
156
+ signature = hmac.new(
157
+ signing_key, string_to_sign.encode("utf-8"), hashlib.sha256
158
+ ).hexdigest()
159
+
160
+ request.headers["Authorization"] = (
161
+ f"{_SIGV4_ALGORITHM} Credential={access_key}/{credential_scope}, "
162
+ f"SignedHeaders={signed_headers}, Signature={signature}"
163
+ )
164
+
165
+
166
+ def _canonical_query_string(query: str) -> str:
167
+ """Build the AWS Sig V4 canonical query string from a raw query string."""
168
+ pairs = urllib.parse.parse_qsl(query, keep_blank_values=True)
169
+ encoded = [
170
+ (
171
+ urllib.parse.quote(key, safe="-_.~"),
172
+ urllib.parse.quote(value, safe="-_.~"),
173
+ )
174
+ for key, value in pairs
175
+ ]
176
+ encoded.sort()
177
+ return "&".join(f"{key}={value}" for key, value in encoded)
178
+
179
+
180
+ def _derive_signing_key(
181
+ secret_key: str, datestamp: str, region: str, service: str
182
+ ) -> bytes:
183
+ """Derive the AWS Sig V4 signing key via the chained HMAC-SHA256 sequence."""
184
+
185
+ def _hmac(key: bytes, msg: str) -> bytes:
186
+ return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
187
+
188
+ k_date = _hmac(f"AWS4{secret_key}".encode(), datestamp)
189
+ k_region = _hmac(k_date, region)
190
+ k_service = _hmac(k_region, service)
191
+ return _hmac(k_service, "aws4_request")
@@ -41,6 +41,7 @@ CREDENTIAL_FILE_ENV_VAR = "DATACUSTOMCODE_EXTERNAL_CALLOUT_CONFIG"
41
41
  class AuthType(str, Enum):
42
42
  """External Credential auth types supported by External Services."""
43
43
 
44
+ AWS_SIG_V4 = "AwsSv4"
44
45
  BASIC = "Basic"
45
46
  CUSTOM = "Custom"
46
47
  JWT = "Jwt"
@@ -122,7 +122,7 @@ matching entries in `config.json`) to point at your own DLOs.
122
122
  `auth_type` selects how auth is injected for local testing. It should mirror the
123
123
  External Credential your Named Credential uses in the org, so local and deployed
124
124
  runs behave the same. This example uses `Custom` (Gemini's `X-goog-api-key`);
125
- all four supported types:
125
+ all supported types:
126
126
 
127
127
  | `auth_type` | Fields read | Header sent |
128
128
  | ----------- | ------------------------------- | --------------------------------------- |
@@ -130,7 +130,11 @@ all four supported types:
130
130
  | `Custom` | `custom_headers` (sent verbatim)| the headers you list |
131
131
  | `OAuth` | `access_token` or `token` | `Authorization: Bearer <token>` |
132
132
  | `Jwt` | `access_token` or `token` | `Authorization: Bearer <token>` |
133
+ | `AwsSv4` | `aws_access_key_id`, `aws_secret_access_key`, `aws_region`, `aws_service`, optional `aws_session_token` | `Authorization: AWS4-HMAC-SHA256 ...` plus `x-amz-date` / `x-amz-content-sha256` (and `x-amz-security-token` when a session token is set) |
133
134
 
134
135
  `OAuth`/`Jwt` take a token you supply for the local run — the SDK does not fetch
135
136
  or refresh it. In the Data Cloud runtime the Named Credential handles token
136
137
  acquisition; this local config only stands in for that during testing.
138
+
139
+ `AwsSv4` signs the request with AWS Signature Version 4 using the keys you
140
+ supply, mirroring an AWS Signature Version 4 External Credential in the org.
@@ -1,63 +0,0 @@
1
- # Copyright (c) 2025, Salesforce, Inc.
2
- # SPDX-License-Identifier: Apache-2
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- """
16
- Inject external credential auth into an outgoing request.
17
- """
18
-
19
- from __future__ import annotations
20
-
21
- import base64
22
- from typing import (
23
- TYPE_CHECKING,
24
- Any,
25
- Dict,
26
- )
27
-
28
- from requests.auth import AuthBase
29
-
30
- from datacustomcode.named_credential.direct.credentials import AuthType
31
-
32
- if TYPE_CHECKING:
33
- from requests.models import PreparedRequest
34
-
35
-
36
- class DynamicAuthHandler(AuthBase):
37
- def __init__(self, cred_config: Dict[str, Any]) -> None:
38
- self.config = cred_config
39
- self.auth_type = cred_config.get("auth_type")
40
-
41
- def __call__(self, request: PreparedRequest) -> PreparedRequest:
42
- if self.auth_type == AuthType.BASIC.value:
43
- user = self.config.get("username", "")
44
- pwd = self.config.get("password", "")
45
- token = base64.b64encode(f"{user}:{pwd}".encode()).decode()
46
- request.headers["Authorization"] = f"Basic {token}"
47
-
48
- elif self.auth_type == AuthType.CUSTOM.value:
49
- for name, value in self.config.get("custom_headers", {}).items():
50
- request.headers[name] = value
51
-
52
- elif self.auth_type in (AuthType.OAUTH.value, AuthType.JWT.value):
53
- bearer = self.config.get("access_token") or self.config.get("token")
54
- if not bearer:
55
- raise ValueError(
56
- f"'{self.auth_type}' auth requires an 'access_token' or 'token'."
57
- )
58
- request.headers["Authorization"] = f"Bearer {bearer}"
59
-
60
- else:
61
- raise ValueError(f"Unsupported auth_type '{self.auth_type}'.")
62
-
63
- return request