payi 0.1.0a89__tar.gz → 0.1.0a91__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.

Potentially problematic release.


This version of payi might be problematic. Click here for more details.

Files changed (209) hide show
  1. payi-0.1.0a91/.release-please-manifest.json +3 -0
  2. {payi-0.1.0a89 → payi-0.1.0a91}/CHANGELOG.md +44 -0
  3. {payi-0.1.0a89 → payi-0.1.0a91}/PKG-INFO +41 -3
  4. {payi-0.1.0a89 → payi-0.1.0a91}/README.md +37 -2
  5. {payi-0.1.0a89 → payi-0.1.0a91}/pyproject.toml +5 -2
  6. {payi-0.1.0a89 → payi-0.1.0a91}/requirements-dev.lock +31 -1
  7. {payi-0.1.0a89 → payi-0.1.0a91}/requirements.lock +27 -1
  8. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/__init__.py +2 -1
  9. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_base_client.py +38 -2
  10. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_version.py +1 -1
  11. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/AnthropicInstrumentor.py +32 -1
  12. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/BedrockInstrumentor.py +18 -0
  13. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/OpenAIInstrumentor.py +47 -3
  14. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/VertexRequest.py +17 -1
  15. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/instrument.py +20 -0
  16. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/categories/test_fixed_cost_resources.py +3 -1
  17. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/categories/test_resources.py +3 -1
  18. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/experiences/test_properties.py +3 -1
  19. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/experiences/test_types.py +3 -1
  20. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/experiences/types/test_limit_config.py +3 -1
  21. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/limits/test_tags.py +3 -1
  22. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/requests/test_properties.py +3 -1
  23. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/requests/test_result.py +3 -1
  24. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/test_categories.py +3 -1
  25. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/test_experiences.py +3 -1
  26. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/test_ingest.py +3 -1
  27. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/test_limits.py +3 -1
  28. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/test_use_cases.py +3 -1
  29. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/definitions/test_kpis.py +3 -1
  30. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/definitions/test_limit_config.py +3 -1
  31. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/definitions/test_version.py +3 -1
  32. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/test_definitions.py +3 -1
  33. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/test_kpis.py +3 -1
  34. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/test_properties.py +3 -1
  35. {payi-0.1.0a89 → payi-0.1.0a91}/tests/conftest.py +39 -6
  36. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_client.py +66 -58
  37. payi-0.1.0a89/.release-please-manifest.json +0 -3
  38. {payi-0.1.0a89 → payi-0.1.0a91}/.gitignore +0 -0
  39. {payi-0.1.0a89 → payi-0.1.0a91}/CONTRIBUTING.md +0 -0
  40. {payi-0.1.0a89 → payi-0.1.0a91}/LICENSE +0 -0
  41. {payi-0.1.0a89 → payi-0.1.0a91}/SECURITY.md +0 -0
  42. {payi-0.1.0a89 → payi-0.1.0a91}/api.md +0 -0
  43. {payi-0.1.0a89 → payi-0.1.0a91}/bin/check-release-environment +0 -0
  44. {payi-0.1.0a89 → payi-0.1.0a91}/bin/publish-pypi +0 -0
  45. {payi-0.1.0a89 → payi-0.1.0a91}/examples/.keep +0 -0
  46. {payi-0.1.0a89 → payi-0.1.0a91}/mypy.ini +0 -0
  47. {payi-0.1.0a89 → payi-0.1.0a91}/noxfile.py +0 -0
  48. {payi-0.1.0a89 → payi-0.1.0a91}/release-please-config.json +0 -0
  49. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_client.py +0 -0
  50. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_compat.py +0 -0
  51. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_constants.py +0 -0
  52. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_exceptions.py +0 -0
  53. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_files.py +0 -0
  54. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_models.py +0 -0
  55. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_qs.py +0 -0
  56. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_resource.py +0 -0
  57. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_response.py +0 -0
  58. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_streaming.py +0 -0
  59. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_types.py +0 -0
  60. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/__init__.py +0 -0
  61. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_logs.py +0 -0
  62. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_proxy.py +0 -0
  63. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_reflection.py +0 -0
  64. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_resources_proxy.py +0 -0
  65. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_streams.py +0 -0
  66. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_sync.py +0 -0
  67. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_transform.py +0 -0
  68. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_typing.py +0 -0
  69. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/_utils/_utils.py +0 -0
  70. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/.keep +0 -0
  71. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/GoogleGenAiInstrumentor.py +0 -0
  72. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/Stopwatch.py +0 -0
  73. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/VertexInstrumentor.py +0 -0
  74. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/lib/helpers.py +0 -0
  75. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/pagination.py +0 -0
  76. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/py.typed +0 -0
  77. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/__init__.py +0 -0
  78. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/categories/__init__.py +0 -0
  79. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/categories/categories.py +0 -0
  80. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/categories/fixed_cost_resources.py +0 -0
  81. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/categories/resources.py +0 -0
  82. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/experiences/__init__.py +0 -0
  83. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/experiences/experiences.py +0 -0
  84. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/experiences/properties.py +0 -0
  85. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/experiences/types/__init__.py +0 -0
  86. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/experiences/types/limit_config.py +0 -0
  87. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/experiences/types/types.py +0 -0
  88. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/ingest.py +0 -0
  89. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/limits/__init__.py +0 -0
  90. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/limits/limits.py +0 -0
  91. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/limits/tags.py +0 -0
  92. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/requests/__init__.py +0 -0
  93. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/requests/properties.py +0 -0
  94. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/requests/requests.py +0 -0
  95. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/requests/result.py +0 -0
  96. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/__init__.py +0 -0
  97. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/definitions/__init__.py +0 -0
  98. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/definitions/definitions.py +0 -0
  99. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/definitions/kpis.py +0 -0
  100. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/definitions/limit_config.py +0 -0
  101. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/definitions/version.py +0 -0
  102. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/kpis.py +0 -0
  103. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/properties.py +0 -0
  104. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/resources/use_cases/use_cases.py +0 -0
  105. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/__init__.py +0 -0
  106. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/bulk_ingest_response.py +0 -0
  107. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/categories/__init__.py +0 -0
  108. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/categories/fixed_cost_resource_create_params.py +0 -0
  109. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/categories/resource_create_params.py +0 -0
  110. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/categories/resource_list_params.py +0 -0
  111. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/category_delete_resource_response.py +0 -0
  112. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/category_delete_response.py +0 -0
  113. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/category_list_params.py +0 -0
  114. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/category_list_resources_params.py +0 -0
  115. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/category_resource_response.py +0 -0
  116. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/category_response.py +0 -0
  117. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/cost_data.py +0 -0
  118. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/cost_details.py +0 -0
  119. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/default_response.py +0 -0
  120. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experience_instance_response.py +0 -0
  121. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/__init__.py +0 -0
  122. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/experience_type.py +0 -0
  123. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/property_create_params.py +0 -0
  124. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/type_create_params.py +0 -0
  125. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/type_list_params.py +0 -0
  126. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/type_update_params.py +0 -0
  127. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/types/__init__.py +0 -0
  128. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/experiences/types/limit_config_create_params.py +0 -0
  129. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/ingest_bulk_params.py +0 -0
  130. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/ingest_event_param.py +0 -0
  131. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/ingest_response.py +0 -0
  132. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/ingest_units_params.py +0 -0
  133. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_create_params.py +0 -0
  134. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_history_response.py +0 -0
  135. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_list_params.py +0 -0
  136. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_list_response.py +0 -0
  137. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_reset_params.py +0 -0
  138. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_response.py +0 -0
  139. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limit_update_params.py +0 -0
  140. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/__init__.py +0 -0
  141. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/limit_tags.py +0 -0
  142. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_create_params.py +0 -0
  143. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_create_response.py +0 -0
  144. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_delete_response.py +0 -0
  145. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_list_response.py +0 -0
  146. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_remove_params.py +0 -0
  147. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_remove_response.py +0 -0
  148. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_update_params.py +0 -0
  149. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/limits/tag_update_response.py +0 -0
  150. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/pay_i_common_models_api_router_header_info_param.py +0 -0
  151. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/requests/__init__.py +0 -0
  152. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/requests/property_create_params.py +0 -0
  153. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/requests/request_result.py +0 -0
  154. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/requests_data.py +0 -0
  155. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/__init__.py +0 -0
  156. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/evaluation_response.py +0 -0
  157. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/ingest_units.py +0 -0
  158. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/pay_i_common_models_budget_management_cost_details_base.py +0 -0
  159. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/pay_i_common_models_budget_management_create_limit_base.py +0 -0
  160. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/properties_response.py +0 -0
  161. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/xproxy_error.py +0 -0
  162. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared/xproxy_result.py +0 -0
  163. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared_params/__init__.py +0 -0
  164. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared_params/ingest_units.py +0 -0
  165. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/shared_params/pay_i_common_models_budget_management_create_limit_base.py +0 -0
  166. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/total_cost_data.py +0 -0
  167. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_case_instance_response.py +0 -0
  168. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/__init__.py +0 -0
  169. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definition_create_params.py +0 -0
  170. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definition_list_params.py +0 -0
  171. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definition_update_params.py +0 -0
  172. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/__init__.py +0 -0
  173. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_create_params.py +0 -0
  174. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_create_response.py +0 -0
  175. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_delete_response.py +0 -0
  176. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_list_params.py +0 -0
  177. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_list_response.py +0 -0
  178. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_retrieve_response.py +0 -0
  179. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_update_params.py +0 -0
  180. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/kpi_update_response.py +0 -0
  181. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/definitions/limit_config_create_params.py +0 -0
  182. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/kpi_create_params.py +0 -0
  183. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/kpi_list_params.py +0 -0
  184. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/kpi_list_response.py +0 -0
  185. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/kpi_update_params.py +0 -0
  186. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/property_create_params.py +0 -0
  187. {payi-0.1.0a89 → payi-0.1.0a91}/src/payi/types/use_cases/use_case_definition.py +0 -0
  188. {payi-0.1.0a89 → payi-0.1.0a91}/tests/__init__.py +0 -0
  189. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/__init__.py +0 -0
  190. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/categories/__init__.py +0 -0
  191. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/experiences/__init__.py +0 -0
  192. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/experiences/types/__init__.py +0 -0
  193. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/limits/__init__.py +0 -0
  194. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/requests/__init__.py +0 -0
  195. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/__init__.py +0 -0
  196. {payi-0.1.0a89 → payi-0.1.0a91}/tests/api_resources/use_cases/definitions/__init__.py +0 -0
  197. {payi-0.1.0a89 → payi-0.1.0a91}/tests/sample_file.txt +0 -0
  198. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_deepcopy.py +0 -0
  199. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_extract_files.py +0 -0
  200. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_files.py +0 -0
  201. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_models.py +0 -0
  202. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_qs.py +0 -0
  203. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_required_args.py +0 -0
  204. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_response.py +0 -0
  205. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_streaming.py +0 -0
  206. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_transform.py +0 -0
  207. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_utils/test_proxy.py +0 -0
  208. {payi-0.1.0a89 → payi-0.1.0a91}/tests/test_utils/test_typing.py +0 -0
  209. {payi-0.1.0a89 → payi-0.1.0a91}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0-alpha.91"
3
+ }
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.91 (2025-06-25)
4
+
5
+ Full Changelog: [v0.1.0-alpha.90...v0.1.0-alpha.91](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.90...v0.1.0-alpha.91)
6
+
7
+ ### Features
8
+
9
+ * do not instrument inline base64 image data by default ([#331](https://github.com/Pay-i/pay-i-python/issues/331)) ([8b0455d](https://github.com/Pay-i/pay-i-python/commit/8b0455d24cda3060bc2170b05e5438c72885bf1a))
10
+
11
+
12
+ ### Chores
13
+
14
+ * **tests:** skip some failing tests on the latest python versions ([1856b99](https://github.com/Pay-i/pay-i-python/commit/1856b99b5802dc02e4f536818f1a205d9da708c2))
15
+
16
+ ## 0.1.0-alpha.90 (2025-06-23)
17
+
18
+ Full Changelog: [v0.1.0-alpha.89...v0.1.0-alpha.90](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.89...v0.1.0-alpha.90)
19
+
20
+ ### Features
21
+
22
+ * **client:** add support for aiohttp ([e875663](https://github.com/Pay-i/pay-i-python/commit/e87566399607c87091b4a83f855910b78107e31b))
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **client:** correctly parse binary response | stream ([6bb78c4](https://github.com/Pay-i/pay-i-python/commit/6bb78c4488dc3af5d556c1a063372be6ae018342))
28
+ * **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([eb727c7](https://github.com/Pay-i/pay-i-python/commit/eb727c742f8f6ac0c9487d7ff4e6e7698afacd0d))
29
+
30
+
31
+ ### Chores
32
+
33
+ * **ci:** enable for pull requests ([e999e4e](https://github.com/Pay-i/pay-i-python/commit/e999e4ee3a05ea8dcb8518eaba1e6ea5f3f958e0))
34
+ * **internal:** update conftest.py ([d668101](https://github.com/Pay-i/pay-i-python/commit/d66810199d9394852f8c5783801fc055745a3ef2))
35
+ * **internal:** version bump ([5616a6a](https://github.com/Pay-i/pay-i-python/commit/5616a6a1147d94e8ca69350dd5b21a211b9eed75))
36
+ * **internal:** version bump ([d93bffd](https://github.com/Pay-i/pay-i-python/commit/d93bffd3f408fc6ec34bf4071dddcc2e55653fcc))
37
+ * **internal:** version bump ([d2022a7](https://github.com/Pay-i/pay-i-python/commit/d2022a710955c9bbf6683a96bc3e2fd46a14c3e7))
38
+ * **readme:** update badges ([5219fd7](https://github.com/Pay-i/pay-i-python/commit/5219fd70ef3c88f114f6b69e89caabcf0d5a39e0))
39
+ * **tests:** add tests for httpx client instantiation & proxies ([bafbfd1](https://github.com/Pay-i/pay-i-python/commit/bafbfd154aba87811edb87bf375d8d9242b6a14e))
40
+ * **tests:** run tests in parallel ([6bdbcdd](https://github.com/Pay-i/pay-i-python/commit/6bdbcddb8a4465cc79fee2e0ba66168079a24490))
41
+
42
+
43
+ ### Documentation
44
+
45
+ * **client:** fix httpx.Timeout documentation reference ([60d1b01](https://github.com/Pay-i/pay-i-python/commit/60d1b01aae900736dfe0345aa8250b67fa1ba704))
46
+
3
47
  ## 0.1.0-alpha.89 (2025-06-17)
4
48
 
5
49
  Full Changelog: [v0.1.0-alpha.88...v0.1.0-alpha.89](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.88...v0.1.0-alpha.89)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: payi
3
- Version: 0.1.0a89
3
+ Version: 0.1.0a91
4
4
  Summary: The official Python library for the payi API
5
5
  Project-URL: Homepage, https://github.com/Pay-i/pay-i-python
6
6
  Project-URL: Repository, https://github.com/Pay-i/pay-i-python
@@ -30,11 +30,14 @@ Requires-Dist: sniffio
30
30
  Requires-Dist: tiktoken>=0.8.0
31
31
  Requires-Dist: typing-extensions<5,>=4.10
32
32
  Requires-Dist: wrapt>=1.17.2
33
+ Provides-Extra: aiohttp
34
+ Requires-Dist: aiohttp; extra == 'aiohttp'
35
+ Requires-Dist: httpx-aiohttp>=0.1.6; extra == 'aiohttp'
33
36
  Description-Content-Type: text/markdown
34
37
 
35
38
  # Payi Python API library
36
39
 
37
- [![PyPI version](https://img.shields.io/pypi/v/payi.svg)](https://pypi.org/project/payi/)
40
+ [![PyPI version](https://github.com/Pay-i/pay-i-python/tree/main/<https://img.shields.io/pypi/v/payi.svg?label=pypi%20(stable)>)](https://pypi.org/project/payi/)
38
41
 
39
42
  The Payi Python library provides convenient access to the Payi REST API from any Python 3.8+
40
43
  application. The library includes type definitions for all request params and response fields,
@@ -104,6 +107,41 @@ asyncio.run(main())
104
107
 
105
108
  Functionality between the synchronous and asynchronous clients is otherwise identical.
106
109
 
110
+ ### With aiohttp
111
+
112
+ By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
113
+
114
+ You can enable this by installing `aiohttp`:
115
+
116
+ ```sh
117
+ # install from PyPI
118
+ pip install --pre payi[aiohttp]
119
+ ```
120
+
121
+ Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
122
+
123
+ ```python
124
+ import os
125
+ import asyncio
126
+ from payi import DefaultAioHttpClient
127
+ from payi import AsyncPayi
128
+
129
+
130
+ async def main() -> None:
131
+ async with AsyncPayi(
132
+ api_key=os.environ.get("PAYI_API_KEY"), # This is the default and can be omitted
133
+ http_client=DefaultAioHttpClient(),
134
+ ) as client:
135
+ use_case_definition = await client.use_cases.definitions.create(
136
+ description="Sample Use Case Definition Description",
137
+ name="SampleUseCaseDefinition",
138
+ )
139
+ print(use_case_definition.request_id)
140
+
141
+
142
+ asyncio.run(main())
143
+ ```
144
+
107
145
  ## Using types
108
146
 
109
147
  Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
@@ -264,7 +302,7 @@ client.with_options(max_retries=5).use_cases.definitions.create(
264
302
  ### Timeouts
265
303
 
266
304
  By default requests time out after 1 minute. You can configure this with a `timeout` option,
267
- which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
305
+ which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:
268
306
 
269
307
  ```python
270
308
  from payi import Payi
@@ -1,6 +1,6 @@
1
1
  # Payi Python API library
2
2
 
3
- [![PyPI version](https://img.shields.io/pypi/v/payi.svg)](https://pypi.org/project/payi/)
3
+ [![PyPI version](<https://img.shields.io/pypi/v/payi.svg?label=pypi%20(stable)>)](https://pypi.org/project/payi/)
4
4
 
5
5
  The Payi Python library provides convenient access to the Payi REST API from any Python 3.8+
6
6
  application. The library includes type definitions for all request params and response fields,
@@ -70,6 +70,41 @@ asyncio.run(main())
70
70
 
71
71
  Functionality between the synchronous and asynchronous clients is otherwise identical.
72
72
 
73
+ ### With aiohttp
74
+
75
+ By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
76
+
77
+ You can enable this by installing `aiohttp`:
78
+
79
+ ```sh
80
+ # install from PyPI
81
+ pip install --pre payi[aiohttp]
82
+ ```
83
+
84
+ Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
85
+
86
+ ```python
87
+ import os
88
+ import asyncio
89
+ from payi import DefaultAioHttpClient
90
+ from payi import AsyncPayi
91
+
92
+
93
+ async def main() -> None:
94
+ async with AsyncPayi(
95
+ api_key=os.environ.get("PAYI_API_KEY"), # This is the default and can be omitted
96
+ http_client=DefaultAioHttpClient(),
97
+ ) as client:
98
+ use_case_definition = await client.use_cases.definitions.create(
99
+ description="Sample Use Case Definition Description",
100
+ name="SampleUseCaseDefinition",
101
+ )
102
+ print(use_case_definition.request_id)
103
+
104
+
105
+ asyncio.run(main())
106
+ ```
107
+
73
108
  ## Using types
74
109
 
75
110
  Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
@@ -230,7 +265,7 @@ client.with_options(max_retries=5).use_cases.definitions.create(
230
265
  ### Timeouts
231
266
 
232
267
  By default requests time out after 1 minute. You can configure this with a `timeout` option,
233
- which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
268
+ which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:
234
269
 
235
270
  ```python
236
271
  from payi import Payi
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "payi"
3
- version = "0.1.0-alpha.89"
3
+ version = "0.1.0-alpha.91"
4
4
  description = "The official Python library for the payi API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -40,6 +40,8 @@ classifiers = [
40
40
  Homepage = "https://github.com/Pay-i/pay-i-python"
41
41
  Repository = "https://github.com/Pay-i/pay-i-python"
42
42
 
43
+ [project.optional-dependencies]
44
+ aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.6"]
43
45
 
44
46
  [tool.rye]
45
47
  managed = true
@@ -57,6 +59,7 @@ dev-dependencies = [
57
59
  "importlib-metadata>=6.7.0",
58
60
  "rich>=13.7.1",
59
61
  "nest_asyncio==1.6.0",
62
+ "pytest-xdist>=3.6.1",
60
63
  "wrapt",
61
64
  ]
62
65
 
@@ -129,7 +132,7 @@ replacement = '[\1](https://github.com/Pay-i/pay-i-python/tree/main/\g<2>)'
129
132
 
130
133
  [tool.pytest.ini_options]
131
134
  testpaths = ["tests"]
132
- addopts = "--tb=short"
135
+ addopts = "--tb=short -n auto"
133
136
  xfail_strict = true
134
137
  asyncio_mode = "auto"
135
138
  asyncio_default_fixture_loop_scope = "session"
@@ -10,6 +10,13 @@
10
10
  # universal: false
11
11
 
12
12
  -e file:.
13
+ aiohappyeyeballs==2.6.1
14
+ # via aiohttp
15
+ aiohttp==3.12.8
16
+ # via httpx-aiohttp
17
+ # via payi
18
+ aiosignal==1.3.2
19
+ # via aiohttp
13
20
  annotated-types==0.6.0
14
21
  # via pydantic
15
22
  anyio==4.4.0
@@ -17,6 +24,10 @@ anyio==4.4.0
17
24
  # via payi
18
25
  argcomplete==3.1.2
19
26
  # via nox
27
+ async-timeout==5.0.1
28
+ # via aiohttp
29
+ attrs==25.3.0
30
+ # via aiohttp
20
31
  certifi==2023.7.22
21
32
  # via httpcore
22
33
  # via httpx
@@ -33,19 +44,27 @@ distro==1.8.0
33
44
  exceptiongroup==1.2.2
34
45
  # via anyio
35
46
  # via pytest
47
+ execnet==2.1.1
48
+ # via pytest-xdist
36
49
  filelock==3.12.4
37
50
  # via virtualenv
51
+ frozenlist==1.6.2
52
+ # via aiohttp
53
+ # via aiosignal
38
54
  h11==0.14.0
39
55
  # via httpcore
40
56
  httpcore==1.0.2
41
57
  # via httpx
42
58
  httpx==0.28.1
59
+ # via httpx-aiohttp
43
60
  # via payi
44
61
  # via respx
62
+ httpx-aiohttp==0.1.6
63
+ # via payi
45
64
  idna==3.4
46
65
  # via anyio
47
66
  # via httpx
48
- # via requests
67
+ # via yarl
49
68
  importlib-metadata==7.0.0
50
69
  iniconfig==2.0.0
51
70
  # via pytest
@@ -53,6 +72,9 @@ markdown-it-py==3.0.0
53
72
  # via rich
54
73
  mdurl==0.1.2
55
74
  # via markdown-it-py
75
+ multidict==6.4.4
76
+ # via aiohttp
77
+ # via yarl
56
78
  mypy==1.14.1
57
79
  mypy-extensions==1.0.0
58
80
  # via mypy
@@ -68,6 +90,9 @@ platformdirs==3.11.0
68
90
  # via virtualenv
69
91
  pluggy==1.5.0
70
92
  # via pytest
93
+ propcache==0.3.1
94
+ # via aiohttp
95
+ # via yarl
71
96
  pydantic==2.10.3
72
97
  # via payi
73
98
  pydantic-core==2.27.1
@@ -77,7 +102,9 @@ pygments==2.18.0
77
102
  pyright==1.1.399
78
103
  pytest==8.3.3
79
104
  # via pytest-asyncio
105
+ # via pytest-xdist
80
106
  pytest-asyncio==0.24.0
107
+ pytest-xdist==3.7.0
81
108
  python-dateutil==2.8.2
82
109
  # via time-machine
83
110
  pytz==2023.3.post1
@@ -104,6 +131,7 @@ tomli==2.0.2
104
131
  # via pytest
105
132
  typing-extensions==4.12.2
106
133
  # via anyio
134
+ # via multidict
107
135
  # via mypy
108
136
  # via payi
109
137
  # via pydantic
@@ -115,5 +143,7 @@ virtualenv==20.24.5
115
143
  # via nox
116
144
  wrapt==1.17.2
117
145
  # via payi
146
+ yarl==1.20.0
147
+ # via aiohttp
118
148
  zipp==3.17.0
119
149
  # via importlib-metadata
@@ -10,11 +10,22 @@
10
10
  # universal: false
11
11
 
12
12
  -e file:.
13
+ aiohappyeyeballs==2.6.1
14
+ # via aiohttp
15
+ aiohttp==3.12.8
16
+ # via httpx-aiohttp
17
+ # via payi
18
+ aiosignal==1.3.2
19
+ # via aiohttp
13
20
  annotated-types==0.6.0
14
21
  # via pydantic
15
22
  anyio==4.4.0
16
23
  # via httpx
17
24
  # via payi
25
+ async-timeout==5.0.1
26
+ # via aiohttp
27
+ attrs==25.3.0
28
+ # via aiohttp
18
29
  certifi==2023.7.22
19
30
  # via httpcore
20
31
  # via httpx
@@ -25,16 +36,28 @@ distro==1.8.0
25
36
  # via payi
26
37
  exceptiongroup==1.2.2
27
38
  # via anyio
39
+ frozenlist==1.6.2
40
+ # via aiohttp
41
+ # via aiosignal
28
42
  h11==0.14.0
29
43
  # via httpcore
30
44
  httpcore==1.0.2
31
45
  # via httpx
32
46
  httpx==0.28.1
47
+ # via httpx-aiohttp
48
+ # via payi
49
+ httpx-aiohttp==0.1.6
33
50
  # via payi
34
51
  idna==3.4
35
52
  # via anyio
36
53
  # via httpx
37
- # via requests
54
+ # via yarl
55
+ multidict==6.4.4
56
+ # via aiohttp
57
+ # via yarl
58
+ propcache==0.3.1
59
+ # via aiohttp
60
+ # via yarl
38
61
  nest-asyncio==1.6.0
39
62
  # via payi
40
63
  pydantic==2.10.3
@@ -52,6 +75,7 @@ tiktoken==0.8.0
52
75
  # via payi
53
76
  typing-extensions==4.12.2
54
77
  # via anyio
78
+ # via multidict
55
79
  # via payi
56
80
  # via pydantic
57
81
  # via pydantic-core
@@ -59,3 +83,5 @@ urllib3==2.3.0
59
83
  # via requests
60
84
  wrapt==1.17.2
61
85
  # via payi
86
+ yarl==1.20.0
87
+ # via aiohttp
@@ -26,7 +26,7 @@ from ._exceptions import (
26
26
  UnprocessableEntityError,
27
27
  APIResponseValidationError,
28
28
  )
29
- from ._base_client import DefaultHttpxClient, DefaultAsyncHttpxClient
29
+ from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient
30
30
  from ._utils._logs import setup_logging as _setup_logging
31
31
 
32
32
  __all__ = [
@@ -68,6 +68,7 @@ __all__ = [
68
68
  "DEFAULT_CONNECTION_LIMITS",
69
69
  "DefaultHttpxClient",
70
70
  "DefaultAsyncHttpxClient",
71
+ "DefaultAioHttpClient",
71
72
  ]
72
73
 
73
74
  if not _t.TYPE_CHECKING:
@@ -1071,7 +1071,14 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1071
1071
  ) -> ResponseT:
1072
1072
  origin = get_origin(cast_to) or cast_to
1073
1073
 
1074
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1074
+ if (
1075
+ inspect.isclass(origin)
1076
+ and issubclass(origin, BaseAPIResponse)
1077
+ # we only want to actually return the custom BaseAPIResponse class if we're
1078
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1079
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1080
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1081
+ ):
1075
1082
  if not issubclass(origin, APIResponse):
1076
1083
  raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
1077
1084
 
@@ -1282,6 +1289,24 @@ class _DefaultAsyncHttpxClient(httpx.AsyncClient):
1282
1289
  super().__init__(**kwargs)
1283
1290
 
1284
1291
 
1292
+ try:
1293
+ import httpx_aiohttp
1294
+ except ImportError:
1295
+
1296
+ class _DefaultAioHttpClient(httpx.AsyncClient):
1297
+ def __init__(self, **_kwargs: Any) -> None:
1298
+ raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra")
1299
+ else:
1300
+
1301
+ class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
1302
+ def __init__(self, **kwargs: Any) -> None:
1303
+ kwargs.setdefault("timeout", DEFAULT_TIMEOUT)
1304
+ kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS)
1305
+ kwargs.setdefault("follow_redirects", True)
1306
+
1307
+ super().__init__(**kwargs)
1308
+
1309
+
1285
1310
  if TYPE_CHECKING:
1286
1311
  DefaultAsyncHttpxClient = httpx.AsyncClient
1287
1312
  """An alias to `httpx.AsyncClient` that provides the same defaults that this SDK
@@ -1290,8 +1315,12 @@ if TYPE_CHECKING:
1290
1315
  This is useful because overriding the `http_client` with your own instance of
1291
1316
  `httpx.AsyncClient` will result in httpx's defaults being used, not ours.
1292
1317
  """
1318
+
1319
+ DefaultAioHttpClient = httpx.AsyncClient
1320
+ """An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`."""
1293
1321
  else:
1294
1322
  DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient
1323
+ DefaultAioHttpClient = _DefaultAioHttpClient
1295
1324
 
1296
1325
 
1297
1326
  class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient):
@@ -1574,7 +1603,14 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1574
1603
  ) -> ResponseT:
1575
1604
  origin = get_origin(cast_to) or cast_to
1576
1605
 
1577
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1606
+ if (
1607
+ inspect.isclass(origin)
1608
+ and issubclass(origin, BaseAPIResponse)
1609
+ # we only want to actually return the custom BaseAPIResponse class if we're
1610
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1611
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1612
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1613
+ ):
1578
1614
  if not issubclass(origin, AsyncAPIResponse):
1579
1615
  raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
1580
1616
 
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "payi"
4
- __version__ = "0.1.0-alpha.89" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.91" # x-release-please-version
@@ -173,10 +173,15 @@ class _AnthropicProviderRequest(_ProviderRequest):
173
173
 
174
174
  messages = kwargs.get("messages")
175
175
  if messages:
176
+
176
177
  anthropic_has_image_and_get_texts(self, messages)
177
178
 
178
179
  return True
179
180
 
181
+ @override
182
+ def remove_inline_data(self, prompt: 'dict[str, Any]') -> bool:
183
+ return anthropic_remove_inline_data(prompt)
184
+
180
185
  @override
181
186
  def process_exception(self, exception: Exception, kwargs: Any, ) -> bool:
182
187
  try:
@@ -352,4 +357,30 @@ def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'li
352
357
  token_count = sum(len(encoding.encode(item.get("text", ""))) for item in content if item.get("type") == "text")
353
358
  return has_image, token_count
354
359
 
355
- return False, 0
360
+ return False, 0
361
+
362
+ def anthropic_remove_inline_data(prompt: 'dict[str, Any]') -> bool:# noqa: ARG002
363
+ messages = prompt.get("messages", [])
364
+ if not messages:
365
+ return False
366
+
367
+ modified = False
368
+ for message in messages:
369
+ content = message.get('content', Any)
370
+ if not content or not isinstance(content, list):
371
+ continue
372
+
373
+ for item in content: # type: ignore
374
+ if not isinstance(item, dict):
375
+ continue
376
+ # item: dict[str, Any]
377
+ type = item.get("type", "") # type: ignore
378
+ if type != "image":
379
+ continue
380
+
381
+ source = item.get("source", {}) # type: ignore
382
+ if source.get("type", "") == "base64": # type: ignore
383
+ source["data"] = _PayiInstrumentor._not_instrumented
384
+ modified = True
385
+
386
+ return modified
@@ -356,6 +356,24 @@ class _BedrockInvokeProviderRequest(_BedrockProviderRequest):
356
356
 
357
357
  return response
358
358
 
359
+ @override
360
+ def remove_inline_data(self, prompt: 'dict[str, Any]') -> bool:# noqa: ARG002
361
+ if not self._is_anthropic:
362
+ return False
363
+
364
+ from .AnthropicInstrumentor import anthropic_remove_inline_data
365
+ body = prompt.get("body", "")
366
+ if not body:
367
+ return False
368
+
369
+ body_json = json.loads(body)
370
+
371
+ if anthropic_remove_inline_data(body_json):
372
+ prompt["body"] = json.dumps(body_json)
373
+ return True
374
+
375
+ return False
376
+
359
377
  class _BedrockConverseProviderRequest(_BedrockProviderRequest):
360
378
  @override
361
379
  def process_synchronous_response(
@@ -301,9 +301,9 @@ class _OpenAiProviderRequest(_ProviderRequest):
301
301
  units["text"] = Units(input=input, output=output)
302
302
 
303
303
  @staticmethod
304
- def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'list[Any]'], image_type: str = "image_url", text_type:str = "text") -> 'tuple[bool, int]':
304
+ def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'list[Any]'], image_type: str, text_type: str) -> 'tuple[bool, int]':
305
305
  if isinstance(content, list): # type: ignore
306
- has_image = any(item.get("type") == image_type for item in content)
306
+ has_image = any(item.get("type", "") == image_type for item in content)
307
307
  if has_image is False:
308
308
  return has_image, 0
309
309
 
@@ -311,6 +311,28 @@ class _OpenAiProviderRequest(_ProviderRequest):
311
311
  return has_image, token_count
312
312
  return False, 0
313
313
 
314
+ @staticmethod
315
+ def post_process_request_prompt(content: Union[str, 'list[Any]'], image_type: str, url_subkey: bool) -> bool:
316
+ modified = False
317
+ if isinstance(content, list): # type: ignore
318
+ for item in content:
319
+ type = item.get("type", "")
320
+ if type != image_type:
321
+ continue
322
+
323
+ if url_subkey:
324
+ url = item.get("image_url", {}).get("url", "")
325
+ if url.startswith("data:"):
326
+ item["image_url"]["url"] = _PayiInstrumentor._not_instrumented
327
+ modified = True
328
+ else:
329
+ url = item.get("image_url", "")
330
+ if url.startswith("data:"):
331
+ item["image_url"] = _PayiInstrumentor._not_instrumented
332
+ modified = True
333
+
334
+ return modified
335
+
314
336
  class _OpenAiEmbeddingsProviderRequest(_OpenAiProviderRequest):
315
337
  def __init__(self, instrumentor: _PayiInstrumentor):
316
338
  super().__init__(
@@ -397,7 +419,7 @@ class _OpenAiChatProviderRequest(_OpenAiProviderRequest):
397
419
 
398
420
  if enc:
399
421
  for message in messages:
400
- msg_has_image, msg_prompt_tokens = self.has_image_and_get_texts(enc, message.get('content', ''))
422
+ msg_has_image, msg_prompt_tokens = self.has_image_and_get_texts(enc, message.get('content', ''), image_type="image_url", text_type="text")
401
423
  if msg_has_image:
402
424
  has_image = True
403
425
  estimated_token_count += msg_prompt_tokens
@@ -418,6 +440,13 @@ class _OpenAiChatProviderRequest(_OpenAiProviderRequest):
418
440
  self._include_usage_added = True
419
441
  return True
420
442
 
443
+ @override
444
+ def remove_inline_data(self, prompt: 'dict[str, Any]') -> bool:
445
+ messages = prompt.get("messages", None)
446
+ if not messages:
447
+ return False
448
+ return self.post_process_request_prompt(messages, image_type="image_url", url_subkey=True)
449
+
421
450
  @override
422
451
  def process_synchronous_response(
423
452
  self,
@@ -531,6 +560,21 @@ class _OpenAiResponsesProviderRequest(_OpenAiProviderRequest):
531
560
 
532
561
  return True
533
562
 
563
+ @override
564
+ def remove_inline_data(self, prompt: 'dict[str, Any]') -> bool:
565
+ modified = False
566
+ input = prompt.get("input", [])
567
+ for item in input:
568
+ if not isinstance(item, dict):
569
+ continue
570
+
571
+ for key, value in item.items(): # type: ignore
572
+ if key == "content":
573
+ if isinstance(value, list):
574
+ modified = self.post_process_request_prompt(value, image_type="input_image", url_subkey=False) | modified # type: ignore
575
+
576
+ return modified
577
+
534
578
  @override
535
579
  def process_synchronous_response(
536
580
  self,
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import math
3
3
  from typing import Any, Optional
4
+ from typing_extensions import override
4
5
 
5
6
  from payi.lib.helpers import PayiCategories
6
7
  from payi.types.ingest_units_params import Units
@@ -62,7 +63,22 @@ class _VertexRequest(_ProviderRequest): # type: ignore
62
63
  ingest = True
63
64
 
64
65
  return _ChunkResult(send_chunk_to_caller=True, ingest=ingest)
65
-
66
+
67
+ @override
68
+ def remove_inline_data(self, prompt: 'dict[str, Any]') -> bool:
69
+ modified = False
70
+
71
+ parts: list[dict[str, Any]] = prompt["contents"].get("parts", [])
72
+ for part in parts:
73
+ inline_data = part.get("inline_data", {})
74
+ if not isinstance(inline_data, dict):
75
+ continue
76
+ if "data" in inline_data:
77
+ inline_data["data"] = _PayiInstrumentor._not_instrumented
78
+ modified = True
79
+
80
+ return modified
81
+
66
82
  def process_response_part_for_function_call(self, part: 'dict[str, Any]') -> None:
67
83
  function = part.get("function_call", {})
68
84
  if not function: