connector-py 4.179.0__tar.gz → 4.181.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. {connector_py-4.179.0 → connector_py-4.181.0}/PKG-INFO +2 -2
  2. connector_py-4.181.0/connector/__about__.py +1 -0
  3. {connector_py-4.179.0 → connector_py-4.181.0}/connector/client.py +6 -1
  4. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/__init__.py +0 -4
  5. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/__init__.py +0 -4
  6. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/base_clients.py +101 -6
  7. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/capabilities/executor.py +2 -2
  8. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/capabilities/factory.py +5 -2
  9. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/capability.py +13 -0
  10. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/integration.py +21 -5
  11. connector_py-4.181.0/connector/oai/modules/credentials_module.py +282 -0
  12. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/modules/info_module.py +126 -82
  13. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/modules/oauth_module.py +1 -1
  14. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/modules/oauth_module_types.py +0 -2
  15. {connector_py-4.179.0 → connector_py-4.181.0}/connector/spec/openapi.yaml +233 -63
  16. {connector_py-4.179.0 → connector_py-4.181.0}/connector_py.egg-info/PKG-INFO +2 -2
  17. {connector_py-4.179.0 → connector_py-4.181.0}/connector_py.egg-info/SOURCES.txt +4 -2
  18. {connector_py-4.179.0 → connector_py-4.181.0}/connector_py.egg-info/requires.txt +1 -1
  19. {connector_py-4.179.0 → connector_py-4.181.0}/pyproject.toml +1 -1
  20. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/capabilities/test_executor_cases.py +3 -3
  21. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/capabilities/test_factory.py +1 -1
  22. connector_py-4.181.0/tests/oai/schema_linter_checks.py +191 -0
  23. connector_py-4.181.0/tests/oai/test_appinfo_all_connectors.py +155 -0
  24. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_base_clients.py +366 -1
  25. connector_py-4.181.0/tests/oai/test_credentials_module.py +740 -0
  26. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_dispatch_cases.py +1 -2
  27. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_info_cases.py +484 -2
  28. connector_py-4.181.0/tests/oai/test_info_module.py +2772 -0
  29. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_oauth_module.py +1 -2
  30. connector_py-4.179.0/connector/__about__.py +0 -1
  31. connector_py-4.179.0/connector/generated/models/auth_model.py +0 -9
  32. connector_py-4.179.0/connector/generated/models/credential_config.py +0 -9
  33. connector_py-4.179.0/tests/oai/test_info_module.py +0 -124
  34. {connector_py-4.179.0 → connector_py-4.181.0}/LICENSE.txt +0 -0
  35. {connector_py-4.179.0 → connector_py-4.181.0}/README.md +0 -0
  36. {connector_py-4.179.0 → connector_py-4.181.0}/connector/__init__.py +0 -0
  37. {connector_py-4.179.0 → connector_py-4.181.0}/connector/auth_helper.py +0 -0
  38. {connector_py-4.179.0 → connector_py-4.181.0}/connector/ca_certs.py +0 -0
  39. {connector_py-4.179.0 → connector_py-4.181.0}/connector/cli.py +0 -0
  40. {connector_py-4.179.0 → connector_py-4.181.0}/connector/compile.py +0 -0
  41. {connector_py-4.179.0 → connector_py-4.181.0}/connector/config.py +0 -0
  42. {connector_py-4.179.0 → connector_py-4.181.0}/connector/error.py +0 -0
  43. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/account_status.py +0 -0
  44. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/account_type.py +0 -0
  45. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activate_account.py +0 -0
  46. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activate_account200_response.py +0 -0
  47. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activate_account_request.py +0 -0
  48. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activate_account_response.py +0 -0
  49. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activated_account.py +0 -0
  50. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_event_type.py +0 -0
  51. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_record.py +0 -0
  52. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_record_activity_type.py +0 -0
  53. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_record_actor.py +0 -0
  54. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_record_entitlement.py +0 -0
  55. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_record_target.py +0 -0
  56. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/activity_type.py +0 -0
  57. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/amount.py +0 -0
  58. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/app_category.py +0 -0
  59. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/app_info.py +0 -0
  60. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/app_info200_response.py +0 -0
  61. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/app_info_request.py +0 -0
  62. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/app_info_request_payload.py +0 -0
  63. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/app_info_response.py +0 -0
  64. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/assign_entitlement.py +0 -0
  65. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/assign_entitlement200_response.py +0 -0
  66. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/assign_entitlement_request.py +0 -0
  67. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/assign_entitlement_response.py +0 -0
  68. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/assigned_entitlement.py +0 -0
  69. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/auth_credential.py +0 -0
  70. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/authorization_url.py +0 -0
  71. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/basic_authentication.py +0 -0
  72. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/basic_credential.py +0 -0
  73. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/capability_schema.py +0 -0
  74. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/creatable_account.py +0 -0
  75. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/create_account.py +0 -0
  76. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/create_account200_response.py +0 -0
  77. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/create_account_entitlement.py +0 -0
  78. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/create_account_request.py +0 -0
  79. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/create_account_response.py +0 -0
  80. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/created_account.py +0 -0
  81. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/custom_attribute_customized_type.py +0 -0
  82. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/custom_attribute_schema.py +0 -0
  83. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/custom_attribute_type.py +0 -0
  84. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/deactivate_account.py +0 -0
  85. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/deactivate_account200_response.py +0 -0
  86. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/deactivate_account_request.py +0 -0
  87. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/deactivate_account_response.py +0 -0
  88. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/deactivated_account.py +0 -0
  89. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/delete_account.py +0 -0
  90. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/delete_account200_response.py +0 -0
  91. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/delete_account_request.py +0 -0
  92. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/delete_account_response.py +0 -0
  93. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/deleted_account.py +0 -0
  94. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/downgrade_license.py +0 -0
  95. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/downgrade_license200_response.py +0 -0
  96. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/downgrade_license_request.py +0 -0
  97. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/downgrade_license_response.py +0 -0
  98. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/downgraded_license.py +0 -0
  99. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/entitlement_requirement.py +0 -0
  100. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/entitlement_type.py +0 -0
  101. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/error.py +0 -0
  102. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/error_code.py +0 -0
  103. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/error_response.py +0 -0
  104. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/expense.py +0 -0
  105. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/expense_approval_status.py +0 -0
  106. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/expense_filters.py +0 -0
  107. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/expense_payment_status.py +0 -0
  108. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/expense_type.py +0 -0
  109. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/find_entitlement_associations.py +0 -0
  110. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/find_entitlement_associations200_response.py +0 -0
  111. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/find_entitlement_associations_request.py +0 -0
  112. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/find_entitlement_associations_response.py +0 -0
  113. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/found_account_data.py +0 -0
  114. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/found_entitlement_association.py +0 -0
  115. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/found_entitlement_data.py +0 -0
  116. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/found_resource_data.py +0 -0
  117. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_account.py +0 -0
  118. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_account200_response.py +0 -0
  119. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_account_request.py +0 -0
  120. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_account_response.py +0 -0
  121. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_authorization_url.py +0 -0
  122. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_authorization_url200_response.py +0 -0
  123. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_authorization_url_request.py +0 -0
  124. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_authorization_url_response.py +0 -0
  125. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_connected_info.py +0 -0
  126. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_connected_info200_response.py +0 -0
  127. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_connected_info_request.py +0 -0
  128. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_connected_info_response.py +0 -0
  129. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_last_activity.py +0 -0
  130. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_last_activity200_response.py +0 -0
  131. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_last_activity_request.py +0 -0
  132. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/get_last_activity_response.py +0 -0
  133. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_authorization_callback.py +0 -0
  134. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_authorization_callback200_response.py +0 -0
  135. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_authorization_callback_request.py +0 -0
  136. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_authorization_callback_response.py +0 -0
  137. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_client_credentials.py +0 -0
  138. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_client_credentials_request.py +0 -0
  139. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_client_credentials_request200_response.py +0 -0
  140. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/handle_client_credentials_response.py +0 -0
  141. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/info.py +0 -0
  142. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/info200_response.py +0 -0
  143. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/info_response.py +0 -0
  144. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/jwt_claims.py +0 -0
  145. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/jwt_credential.py +0 -0
  146. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/jwt_headers.py +0 -0
  147. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/last_activity_data.py +0 -0
  148. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_accounts.py +0 -0
  149. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_accounts200_response.py +0 -0
  150. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_accounts_request.py +0 -0
  151. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_accounts_response.py +0 -0
  152. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_activity_records.py +0 -0
  153. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_activity_records200_response.py +0 -0
  154. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_activity_records_request.py +0 -0
  155. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_activity_records_response.py +0 -0
  156. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_connector_app_ids200_response.py +0 -0
  157. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_custom_attributes_schema.py +0 -0
  158. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_custom_attributes_schema200_response.py +0 -0
  159. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_custom_attributes_schema_request.py +0 -0
  160. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_custom_attributes_schema_response.py +0 -0
  161. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_entitlements.py +0 -0
  162. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_entitlements200_response.py +0 -0
  163. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_entitlements_request.py +0 -0
  164. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_entitlements_response.py +0 -0
  165. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_expenses.py +0 -0
  166. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_expenses200_response.py +0 -0
  167. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_expenses_request.py +0 -0
  168. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_expenses_response.py +0 -0
  169. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_resources.py +0 -0
  170. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_resources200_response.py +0 -0
  171. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_resources_request.py +0 -0
  172. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/list_resources_response.py +0 -0
  173. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/normalized_expense_approval_status.py +0 -0
  174. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/normalized_expense_payment_status.py +0 -0
  175. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth1_credential.py +0 -0
  176. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_authentication.py +0 -0
  177. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_authorization.py +0 -0
  178. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_client_credential.py +0 -0
  179. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_client_credential_authentication.py +0 -0
  180. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_client_credential_authorization.py +0 -0
  181. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_credential.py +0 -0
  182. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/o_auth_scopes.py +0 -0
  183. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/oauth_credentials.py +0 -0
  184. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/page.py +0 -0
  185. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/refresh_access_token.py +0 -0
  186. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/refresh_access_token200_response.py +0 -0
  187. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/refresh_access_token_request.py +0 -0
  188. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/refresh_access_token_response.py +0 -0
  189. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/release_resources.py +0 -0
  190. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/release_resources200_response.py +0 -0
  191. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/release_resources_request.py +0 -0
  192. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/release_resources_response.py +0 -0
  193. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/release_resources_status.py +0 -0
  194. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/resource_type.py +0 -0
  195. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/service_account_credential.py +0 -0
  196. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/service_account_type.py +0 -0
  197. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/spend_user.py +0 -0
  198. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/standard_capability_name.py +0 -0
  199. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/time_range.py +0 -0
  200. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/token_authentication.py +0 -0
  201. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/token_credential.py +0 -0
  202. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/token_type.py +0 -0
  203. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/transfer_data.py +0 -0
  204. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/transfer_data200_response.py +0 -0
  205. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/transfer_data_request.py +0 -0
  206. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/transfer_data_response.py +0 -0
  207. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/transfer_data_status.py +0 -0
  208. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/unassign_entitlement.py +0 -0
  209. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/unassign_entitlement200_response.py +0 -0
  210. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/unassign_entitlement_request.py +0 -0
  211. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/unassign_entitlement_response.py +0 -0
  212. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/unassigned_entitlement.py +0 -0
  213. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/update_account200_response.py +0 -0
  214. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/update_account_request.py +0 -0
  215. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/update_account_response.py +0 -0
  216. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/updateable_account.py +0 -0
  217. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/validate_credentials.py +0 -0
  218. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/validate_credentials200_response.py +0 -0
  219. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/validate_credentials_request.py +0 -0
  220. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/validate_credentials_response.py +0 -0
  221. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/validated_credentials.py +0 -0
  222. {connector_py-4.179.0 → connector_py-4.181.0}/connector/generated/models/vendor.py +0 -0
  223. {connector_py-4.179.0 → connector_py-4.181.0}/connector/handlers/lumos_log_handler.py +0 -0
  224. {connector_py-4.179.0 → connector_py-4.181.0}/connector/http_server.py +0 -0
  225. {connector_py-4.179.0 → connector_py-4.181.0}/connector/httpx_rewrite.py +0 -0
  226. {connector_py-4.179.0 → connector_py-4.181.0}/connector/integration.py +0 -0
  227. {connector_py-4.179.0 → connector_py-4.181.0}/connector/main.py +0 -0
  228. {connector_py-4.179.0 → connector_py-4.181.0}/connector/modules.py +0 -0
  229. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/__init__.py +0 -0
  230. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/capabilities/__init__.py +0 -0
  231. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/capabilities/errors.py +0 -0
  232. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/errors.py +0 -0
  233. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/fingerprint.py +0 -0
  234. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/modules/__init__.py +0 -0
  235. {connector_py-4.179.0 → connector_py-4.181.0}/connector/oai/modules/base_module.py +0 -0
  236. {connector_py-4.179.0 → connector_py-4.181.0}/connector/observability/__init__.py +0 -0
  237. {connector_py-4.179.0 → connector_py-4.181.0}/connector/observability/instrument.py +0 -0
  238. {connector_py-4.179.0 → connector_py-4.181.0}/connector/observability/logging.py +0 -0
  239. {connector_py-4.179.0 → connector_py-4.181.0}/connector/observability/observer.py +0 -0
  240. {connector_py-4.179.0 → connector_py-4.181.0}/connector/py.typed +0 -0
  241. {connector_py-4.179.0 → connector_py-4.181.0}/connector/pydantic.py +0 -0
  242. {connector_py-4.179.0 → connector_py-4.181.0}/connector/response_logging.py +0 -0
  243. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/__init__.py +0 -0
  244. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/create.py +0 -0
  245. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/.pre-commit-config.yaml +0 -0
  246. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/LICENSE.txt +0 -0
  247. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/README.md +0 -0
  248. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/__about__.py +0 -0
  249. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/__init__.py +0 -0
  250. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/capabilities_read.py +0 -0
  251. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/capabilities_write.py +0 -0
  252. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/client.py +0 -0
  253. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/constants.py +0 -0
  254. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/dto/__init__.py +0 -0
  255. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/dto/user.py +0 -0
  256. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/enums.py +0 -0
  257. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/integration.py +0 -0
  258. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/main.py +0 -0
  259. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/pagination.py +0 -0
  260. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/connector_name_here/settings.py +0 -0
  261. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/pyproject.toml +0 -0
  262. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/__init__.py +0 -0
  263. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/common_mock_data.py +0 -0
  264. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_all_capabilities.py +0 -0
  265. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/__init__.py +0 -0
  266. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/test_find_entitlement_associations_cases.py +0 -0
  267. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/test_get_last_activity_cases.py +0 -0
  268. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/test_list_accounts_cases.py +0 -0
  269. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/test_list_entitlements_cases.py +0 -0
  270. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/test_list_resources_cases.py +0 -0
  271. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_read_capabilities/test_validate_credentials_cases.py +0 -0
  272. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/__init__.py +0 -0
  273. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/test_activate_account_cases.py +0 -0
  274. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/test_assign_entitlement_cases.py +0 -0
  275. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/test_create_account_cases.py +0 -0
  276. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/test_deactivate_account_cases.py +0 -0
  277. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/test_delete_account_cases.py +0 -0
  278. {connector_py-4.179.0 → connector_py-4.181.0}/connector/scaffold/templates/tests/test_write_capabilities/test_unassign_entitlement_cases.py +0 -0
  279. {connector_py-4.179.0 → connector_py-4.181.0}/connector/serializers/__init__.py +0 -0
  280. {connector_py-4.179.0 → connector_py-4.181.0}/connector/serializers/request.py +0 -0
  281. {connector_py-4.179.0 → connector_py-4.181.0}/connector/shared_types.py +0 -0
  282. {connector_py-4.179.0 → connector_py-4.181.0}/connector/tests/__init__.py +0 -0
  283. {connector_py-4.179.0 → connector_py-4.181.0}/connector/tests/coverage_check.py +0 -0
  284. {connector_py-4.179.0 → connector_py-4.181.0}/connector/tests/gather_cases.py +0 -0
  285. {connector_py-4.179.0 → connector_py-4.181.0}/connector/tests/mock_httpx.py +0 -0
  286. {connector_py-4.179.0 → connector_py-4.181.0}/connector/tests/test_mock_httpx.py +0 -0
  287. {connector_py-4.179.0 → connector_py-4.181.0}/connector/tests/type_definitions.py +0 -0
  288. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/__init__.py +0 -0
  289. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/account.py +0 -0
  290. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/case_insensitive_dict.py +0 -0
  291. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/client_utils.py +0 -0
  292. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/httpx_auth.py +0 -0
  293. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/jwt_utils.py +0 -0
  294. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/oauth1_utils.py +0 -0
  295. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/pagination.py +0 -0
  296. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/proxy_utils.py +0 -0
  297. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/rate_limiting.py +0 -0
  298. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/sync_to_async.py +0 -0
  299. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/test.py +0 -0
  300. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/test_case_insensitive_dict.py +0 -0
  301. {connector_py-4.179.0 → connector_py-4.181.0}/connector/utils/validation_utils.py +0 -0
  302. {connector_py-4.179.0 → connector_py-4.181.0}/connector_py.egg-info/dependency_links.txt +0 -0
  303. {connector_py-4.179.0 → connector_py-4.181.0}/connector_py.egg-info/entry_points.txt +0 -0
  304. {connector_py-4.179.0 → connector_py-4.181.0}/connector_py.egg-info/top_level.txt +0 -0
  305. {connector_py-4.179.0 → connector_py-4.181.0}/setup.cfg +0 -0
  306. {connector_py-4.179.0 → connector_py-4.181.0}/tests/__init__.py +0 -0
  307. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/__init__.py +0 -0
  308. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/capabilities/__init__.py +0 -0
  309. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/capabilities/test_executor.py +0 -0
  310. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/shared_types.py +0 -0
  311. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_capability.py +0 -0
  312. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_dispatch_settings_cases.py +0 -0
  313. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_exception_handler.py +0 -0
  314. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_exception_handler_handled_cases.py +0 -0
  315. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_get_capability_annotations_cases.py +0 -0
  316. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_integration.py +0 -0
  317. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_modules.py +0 -0
  318. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_modules_cases.py +0 -0
  319. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_register_capability_cases.py +0 -0
  320. {connector_py-4.179.0 → connector_py-4.181.0}/tests/oai/test_validate_capability_cases.py +0 -0
  321. {connector_py-4.179.0 → connector_py-4.181.0}/tests/observability/__init__.py +0 -0
  322. {connector_py-4.179.0 → connector_py-4.181.0}/tests/observability/test_instrument.py +0 -0
  323. {connector_py-4.179.0 → connector_py-4.181.0}/tests/observability/test_observer.py +0 -0
  324. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_cli.py +0 -0
  325. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_compile.py +0 -0
  326. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_config.py +0 -0
  327. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_httpx_rewrite.py +0 -0
  328. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_lumos_log_handler.py +0 -0
  329. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_scaffold.py +0 -0
  330. {connector_py-4.179.0 → connector_py-4.181.0}/tests/test_scopes.py +0 -0
  331. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/__init__.py +0 -0
  332. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/definitions.py +0 -0
  333. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_account_utils.py +0 -0
  334. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_client_utils.py +0 -0
  335. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_fixed_rate_limiting.py +0 -0
  336. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_fixed_rate_limiting_concurrent.py +0 -0
  337. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_jwt_utils.py +0 -0
  338. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_pagination.py +0 -0
  339. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_pagination_decode_cases.py +0 -0
  340. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_pagination_duality_cases.py +0 -0
  341. {connector_py-4.179.0 → connector_py-4.181.0}/tests/utils/test_pagination_encode_cases.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: connector-py
3
- Version: 4.179.0
3
+ Version: 4.181.0
4
4
  Summary: An Abstract Tool to Perform Actions on Integrations.
5
5
  Author-email: teamlumos <security@lumos.com>
6
6
  License-Expression: Apache-2.0
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
15
15
  Requires-Python: >=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE.txt
18
- Requires-Dist: connector-sdk-types==0.35.0
18
+ Requires-Dist: connector-sdk-types==0.36.0
19
19
  Requires-Dist: gql[httpx]
20
20
  Requires-Dist: httpx>=0.27.0
21
21
  Requires-Dist: msgpack>=1
@@ -0,0 +1 @@
1
+ __version__ = "4.181.0"
@@ -1,5 +1,9 @@
1
1
  from .httpx_rewrite import AsyncClient, GqlHTTPXAsyncTransport, HTTPXAsyncTransport
2
- from .oai.base_clients import BaseGraphQLSession, BaseIntegrationClient
2
+ from .oai.base_clients import (
3
+ BaseGraphQLSession,
4
+ BaseIntegrationClient,
5
+ RateLimitedHTTPXAsyncTransport,
6
+ )
3
7
  from .oai.capability import (
4
8
  get_basic_auth,
5
9
  get_jwt_auth,
@@ -20,6 +24,7 @@ from .utils.sync_to_async import sync_to_async
20
24
  __all__ = [
21
25
  "GqlHTTPXAsyncTransport",
22
26
  "HTTPXAsyncTransport",
27
+ "RateLimitedHTTPXAsyncTransport",
23
28
  "BaseGraphQLSession",
24
29
  "BaseIntegrationClient",
25
30
  "get_basic_auth",
@@ -40,7 +40,6 @@ from connector_sdk_types.generated.models.assign_entitlement_response import (
40
40
  )
41
41
  from connector_sdk_types.generated.models.assigned_entitlement import AssignedEntitlement
42
42
  from connector_sdk_types.generated.models.auth_credential import AuthCredential
43
- from connector_sdk_types.generated.models.auth_model import AuthModel
44
43
  from connector_sdk_types.generated.models.authorization_url import AuthorizationUrl
45
44
  from connector_sdk_types.generated.models.basic_authentication import BasicAuthentication
46
45
  from connector_sdk_types.generated.models.basic_credential import BasicCredential
@@ -53,7 +52,6 @@ from connector_sdk_types.generated.models.create_account_request import CreateAc
53
52
  from connector_sdk_types.generated.models.create_account_response import CreateAccountResponse
54
53
  from connector_sdk_types.generated.models.created_account import CreatedAccount
55
54
  from connector_sdk_types.generated.models.created_effect import CreatedEffect
56
- from connector_sdk_types.generated.models.credential_config import CredentialConfig
57
55
  from connector_sdk_types.generated.models.custom_attribute_customized_type import (
58
56
  CustomAttributeCustomizedType,
59
57
  )
@@ -320,7 +318,6 @@ __all__ = [
320
318
  "AssignEntitlementResponse",
321
319
  "AssignedEntitlement",
322
320
  "AuthCredential",
323
- "AuthModel",
324
321
  "AuthorizationUrl",
325
322
  "BasicAuthentication",
326
323
  "BasicCredential",
@@ -332,7 +329,6 @@ __all__ = [
332
329
  "CreateAccountRequest",
333
330
  "CreateAccountResponse",
334
331
  "CreatedAccount",
335
- "CredentialConfig",
336
332
  "CustomAttributeCustomizedType",
337
333
  "CustomAttributeSchema",
338
334
  "CustomAttributeType",
@@ -36,7 +36,6 @@ from connector_sdk_types.generated.models.assign_entitlement_response import (
36
36
  )
37
37
  from connector_sdk_types.generated.models.assigned_entitlement import AssignedEntitlement
38
38
  from connector_sdk_types.generated.models.auth_credential import AuthCredential
39
- from connector_sdk_types.generated.models.auth_model import AuthModel
40
39
  from connector_sdk_types.generated.models.authorization_url import AuthorizationUrl
41
40
  from connector_sdk_types.generated.models.basic_authentication import BasicAuthentication
42
41
  from connector_sdk_types.generated.models.basic_credential import BasicCredential
@@ -48,7 +47,6 @@ from connector_sdk_types.generated.models.create_account_entitlement import Crea
48
47
  from connector_sdk_types.generated.models.create_account_request import CreateAccountRequest
49
48
  from connector_sdk_types.generated.models.create_account_response import CreateAccountResponse
50
49
  from connector_sdk_types.generated.models.created_account import CreatedAccount
51
- from connector_sdk_types.generated.models.credential_config import CredentialConfig
52
50
  from connector_sdk_types.generated.models.custom_attribute_customized_type import (
53
51
  CustomAttributeCustomizedType,
54
52
  )
@@ -304,7 +302,6 @@ __all__ = [
304
302
  "AssignEntitlementResponse",
305
303
  "AssignedEntitlement",
306
304
  "AuthCredential",
307
- "AuthModel",
308
305
  "AuthorizationUrl",
309
306
  "BasicAuthentication",
310
307
  "BasicCredential",
@@ -316,7 +313,6 @@ __all__ = [
316
313
  "CreateAccountRequest",
317
314
  "CreateAccountResponse",
318
315
  "CreatedAccount",
319
- "CredentialConfig",
320
316
  "CustomAttributeCustomizedType",
321
317
  "CustomAttributeSchema",
322
318
  "CustomAttributeType",
@@ -10,11 +10,11 @@ from connector_sdk_types.generated import ErrorCode
10
10
  from gql import Client
11
11
  from gql.client import AsyncClientSession
12
12
  from gql.dsl import DSLSchema
13
- from graphql import GraphQLSchema, build_client_schema, build_schema
13
+ from graphql import DocumentNode, GraphQLSchema, build_client_schema, build_schema
14
14
  from httpx import Response
15
15
  from typing_extensions import Self
16
16
 
17
- from connector.httpx_rewrite import AsyncClient
17
+ from connector.httpx_rewrite import AsyncClient, HTTPXAsyncTransport
18
18
  from connector.oai.capability import Request
19
19
  from connector.oai.errors import ConnectorError
20
20
  from connector.utils.rate_limiting import RateLimitConfig, RateLimiter
@@ -178,6 +178,75 @@ class RateLimitedClient(AsyncClient):
178
178
  await self.base_client.__aexit__(exc_type, exc_val, exc_tb)
179
179
 
180
180
 
181
+ class RateLimitedHTTPXAsyncTransport(HTTPXAsyncTransport):
182
+ """A wrapper around HTTPXAsyncTransport that applies rate limiting to GraphQL requests."""
183
+
184
+ def __init__(self, base_transport: HTTPXAsyncTransport, rate_limit_config: RateLimitConfig):
185
+ # Copy all attributes from base transport, but exclude 'execute' to avoid shadowing our method
186
+ base_dict = {k: v for k, v in base_transport.__dict__.items() if k != "execute"}
187
+ self.__dict__.update(base_dict)
188
+ self.base_transport = base_transport
189
+ self.rate_limiter = RateLimiter[Callable[[], Any], Any](rate_limit_config)
190
+
191
+ async def connect(self):
192
+ """Connect the underlying transport and replace its client with a rate-limited one."""
193
+ await self.base_transport.connect()
194
+
195
+ # Replace the base transport's client with a rate-limited version
196
+ if hasattr(self.base_transport, "client") and self.base_transport.client:
197
+ # The transport's client should be our AsyncClient type, but we need to handle the type
198
+ if isinstance(self.base_transport.client, AsyncClient):
199
+ self.base_transport.client = RateLimitedClient(
200
+ self.base_transport.client, self.rate_limiter.config
201
+ )
202
+
203
+ # Copy the client reference
204
+ self.client = self.base_transport.client
205
+
206
+ async def execute(
207
+ self,
208
+ document: DocumentNode,
209
+ variable_values: dict[str, Any] | None = None,
210
+ operation_name: str | None = None,
211
+ extra_args: dict[str, Any] | None = None,
212
+ upload_files: bool = False,
213
+ ):
214
+ """Execute a GraphQL request with rate limiting."""
215
+
216
+ async def request_func():
217
+ result = await self.base_transport.execute(
218
+ document=document,
219
+ variable_values=variable_values,
220
+ operation_name=operation_name,
221
+ extra_args=extra_args,
222
+ upload_files=upload_files,
223
+ )
224
+ return result
225
+
226
+ # Use the rate limiter to execute the request
227
+ responses = await self.rate_limiter.execute_requests([request_func], lambda x: x())
228
+ if responses:
229
+ return responses[0]
230
+
231
+ raise ConnectorError(
232
+ message="No response from GraphQL API",
233
+ error_code=ErrorCode.API_ERROR,
234
+ )
235
+
236
+ def get_state(self) -> tuple[RateLimitConfig, float]:
237
+ """Get the current rate limit state."""
238
+ return self.rate_limiter.config, self.rate_limiter.current_delay
239
+
240
+ async def close(self):
241
+ """Close the underlying transport."""
242
+ if hasattr(self.base_transport, "close"):
243
+ await self.base_transport.close()
244
+
245
+ def __getattr__(self, name):
246
+ """Delegate attribute access to the underlying base_transport."""
247
+ return getattr(self.base_transport, name)
248
+
249
+
181
250
  class BaseIntegrationClient:
182
251
  _http_client: AsyncClient | RateLimitedClient
183
252
  _rate_limit_config: RateLimitConfig | None = None
@@ -248,8 +317,11 @@ class BaseIntegrationClient:
248
317
 
249
318
 
250
319
  class BaseGraphQLSession(AsyncClientSession):
251
- def __init__(self, args: Request):
252
- super().__init__(client=self.build_client(args))
320
+ _rate_limit_config: RateLimitConfig | None = None
321
+
322
+ def __init__(self, args: Request, rate_limit_config: RateLimitConfig | None = None):
323
+ client = self.build_client(args, rate_limit_config)
324
+ super().__init__(client=client)
253
325
 
254
326
  async def __aenter__(self) -> Self:
255
327
  await self.client.__aenter__()
@@ -267,8 +339,31 @@ class BaseGraphQLSession(AsyncClientSession):
267
339
  pass
268
340
 
269
341
  @classmethod
270
- def build_client(cls, args: Request) -> Client:
271
- return Client(**cls.prepare_client_args(args))
342
+ def build_client(
343
+ cls, args: Request, rate_limit_config: RateLimitConfig | None = None
344
+ ) -> Client:
345
+ client_args = cls.prepare_client_args(args)
346
+
347
+ # Apply rate limiting if configured
348
+ rate_limiting = rate_limit_config or cls._rate_limit_config
349
+ if rate_limiting is not None and "transport" in client_args:
350
+ transport = client_args["transport"]
351
+ if isinstance(transport, HTTPXAsyncTransport):
352
+ client_args["transport"] = RateLimitedHTTPXAsyncTransport(transport, rate_limiting)
353
+
354
+ return Client(**client_args)
355
+
356
+ def get_current_rate_limits(self) -> tuple[RateLimitConfig | None, float]:
357
+ """
358
+ Get the current rate limit state.
359
+
360
+ Returns a tuple of the rate limit config and the current delay. (or None if the client is not rate limited)
361
+ """
362
+ if hasattr(self.client, "transport") and isinstance(
363
+ self.client.transport, RateLimitedHTTPXAsyncTransport
364
+ ):
365
+ return self.client.transport.get_state()
366
+ return None, 0
272
367
 
273
368
  @classmethod
274
369
  def load_schema(cls, schema_file_path: str | Path) -> GraphQLSchema:
@@ -8,7 +8,6 @@ from typing import Any, ClassVar, Generic, Literal, TypeVar, cast
8
8
  from connector_sdk_types.generated import (
9
9
  AuthCredential,
10
10
  BasicCredential,
11
- CredentialConfig,
12
11
  ErrorResponse,
13
12
  JWTCredential,
14
13
  KeyPairCredential,
@@ -20,8 +19,9 @@ from connector_sdk_types.generated import (
20
19
  TokenCredential,
21
20
  )
22
21
  from connector_sdk_types.oai.capability import Request
23
- from connector_sdk_types.oai.modules.oauth_module_types import (
22
+ from connector_sdk_types.oai.modules.credentials_module_types import (
24
23
  AuthSetting,
24
+ CredentialConfig,
25
25
  EmptySettings,
26
26
  OAuthConfig,
27
27
  )
@@ -2,9 +2,12 @@ from collections.abc import Mapping, Sequence
2
2
  from functools import partial
3
3
  from typing import Generic, TypeVar
4
4
 
5
- from connector_sdk_types.generated import CredentialConfig
6
5
  from connector_sdk_types.oai.capability import Request
7
- from connector_sdk_types.oai.modules.oauth_module_types import AuthSetting, OAuthConfig
6
+ from connector_sdk_types.oai.modules.credentials_module_types import (
7
+ AuthSetting,
8
+ CredentialConfig,
9
+ OAuthConfig,
10
+ )
8
11
  from pydantic import BaseModel
9
12
 
10
13
  from connector.oai.capability import CapabilityCallableProto, get_capability_annotations
@@ -103,6 +103,8 @@ from connector_sdk_types.generated import (
103
103
  UnassignEntitlementResponse,
104
104
  UpdateAccountRequest,
105
105
  UpdateAccountResponse,
106
+ ValidateCredentialConfigRequest,
107
+ ValidateCredentialConfigResponse,
106
108
  ValidateCredentialsRequest,
107
109
  ValidateCredentialsResponse,
108
110
  )
@@ -829,4 +831,15 @@ _STANDARD_CAPABILITY_SIGNATURES: dict[StandardCapabilityName, CapabilitySignatur
829
831
  envelope_type=UnassignApplicationEntitlementResponse, is_request=False
830
832
  ),
831
833
  ),
834
+ # Per-credential validation capabilities
835
+ StandardCapabilityName.VALIDATE_CREDENTIAL_CONFIG: CapabilitySignature(
836
+ input_payload=_payload_type_data(
837
+ envelope_type=ValidateCredentialConfigRequest,
838
+ is_request=True,
839
+ ),
840
+ output_payload=_payload_type_data(
841
+ envelope_type=ValidateCredentialConfigResponse,
842
+ is_request=False,
843
+ ),
844
+ ),
832
845
  }
@@ -32,15 +32,14 @@ from functools import cached_property
32
32
 
33
33
  from connector_sdk_types.generated import (
34
34
  AppCategory,
35
- AuthModel,
36
35
  BasicCredential,
37
36
  CapabilitySchema,
38
- CredentialConfig,
39
37
  EntitlementType,
40
38
  Info,
41
39
  InfoResponse,
42
40
  JWTCredential,
43
41
  KeyPairCredential,
42
+ OAuth1Credential,
44
43
  OAuthClientCredential,
45
44
  OAuthCredential,
46
45
  ResourceType,
@@ -48,7 +47,14 @@ from connector_sdk_types.generated import (
48
47
  StandardCapabilityName,
49
48
  TokenCredential,
50
49
  )
51
- from connector_sdk_types.oai.modules.oauth_module_types import AuthSetting, EmptySettings
50
+ from connector_sdk_types.oai.modules.credentials_module_types import (
51
+ AuthModel,
52
+ AuthSetting,
53
+ CredentialConfig,
54
+ CredentialsSettings,
55
+ EmptySettings,
56
+ OAuthConfig,
57
+ )
52
58
  from pydantic import BaseModel
53
59
 
54
60
  from connector.oai.capability import (
@@ -58,14 +64,15 @@ from connector.oai.capability import (
58
64
  )
59
65
  from connector.oai.errors import ErrorMap
60
66
  from connector.oai.modules.base_module import BaseIntegrationModule
67
+ from connector.oai.modules.credentials_module import CredentialsModule
61
68
  from connector.oai.modules.info_module import InfoModule
62
69
  from connector.oai.modules.oauth_module import OAuthModule
63
- from connector.oai.modules.oauth_module_types import OAuthConfig, OAuthSettings
70
+ from connector.oai.modules.oauth_module_types import OAuthSettings
64
71
 
65
72
  from .capabilities.errors import CapabilityError, CapabilityNotImplementedError
66
73
  from .capabilities.factory import CapabilityExecutorFactory
67
74
 
68
- AUTH_TYPE_MAP = {
75
+ AUTH_TYPE_MAP: dict[AuthModel, type[BaseModel]] = {
69
76
  AuthModel.OAUTH: OAuthCredential,
70
77
  AuthModel.OAUTH_CLIENT_CREDENTIALS: OAuthClientCredential,
71
78
  AuthModel.BASIC: BasicCredential,
@@ -73,6 +80,7 @@ AUTH_TYPE_MAP = {
73
80
  AuthModel.JWT: JWTCredential,
74
81
  AuthModel.SERVICE_ACCOUNT: ServiceAccountCredential,
75
82
  AuthModel.KEY_PAIR: KeyPairCredential,
83
+ AuthModel.OAUTH1: OAuth1Credential,
76
84
  }
77
85
 
78
86
 
@@ -183,6 +191,7 @@ class Integration:
183
191
  entitlement_types: list[EntitlementType] | None = None,
184
192
  settings_model: type[BaseModel] | None = None,
185
193
  oauth_settings: OAuthSettings | None = None,
194
+ credentials_settings: CredentialsSettings | None = None,
186
195
  ):
187
196
  self.app_id = app_id.strip()
188
197
  self.version = version
@@ -195,6 +204,7 @@ class Integration:
195
204
  self.entitlement_types = entitlement_types or []
196
205
  self.settings_model = settings_model or EmptySettings
197
206
  self.oauth_settings = oauth_settings
207
+ self.credentials_settings = credentials_settings
198
208
 
199
209
  if len(self.app_id) == 0:
200
210
  raise InvalidAppIdError
@@ -219,6 +229,12 @@ class Integration:
219
229
  # Attach the info module (app_info capability)
220
230
  self.add_module(InfoModule())
221
231
 
232
+ # Attach a credentials module if credentials are provided
233
+ if self.credentials:
234
+ self.add_module(
235
+ CredentialsModule(settings=credentials_settings or CredentialsSettings.default())
236
+ )
237
+
222
238
  def add_module(self, module: BaseIntegrationModule):
223
239
  self.modules.append(module)
224
240
  module.register(self)
@@ -0,0 +1,282 @@
1
+ import inspect
2
+ from collections.abc import Awaitable, Sequence
3
+ from typing import TYPE_CHECKING, cast
4
+
5
+ from connector_sdk_types.generated import (
6
+ Error,
7
+ ErrorCode,
8
+ ErrorResponse,
9
+ StandardCapabilityName,
10
+ ValidateCredentialConfigRequest,
11
+ ValidateCredentialConfigResponse,
12
+ ValidatedCredentialConfig,
13
+ )
14
+ from connector_sdk_types.oai.modules.credentials_module_types import (
15
+ CredentialConfig,
16
+ CredentialsSettings,
17
+ OAuthConfig,
18
+ ValidateCredentialConfigCallable,
19
+ )
20
+ from pydantic import ValidationError
21
+
22
+ from connector.oai.capabilities.errors import CapabilityExecutionError
23
+ from connector.oai.modules.base_module import BaseIntegrationModule
24
+
25
+ if TYPE_CHECKING:
26
+ from connector.oai.integration import Integration
27
+
28
+
29
+ class CredentialsModule(BaseIntegrationModule):
30
+ """
31
+ Credentials module is responsible for handling the credentials for an Integration.
32
+ It can register the following capabilities:
33
+ - VALIDATE_CREDENTIAL_CONFIG
34
+
35
+ It can be configured with the following settings:
36
+ - register_validation_capability: bool - Flag that indicates whether the CredentialsModule should register the validate_credential_config capability. Set to `False` to skip registration and implement the capability manually.
37
+
38
+ You can also call the base_validation method to perform base validation on a credential config request.
39
+
40
+ Example usage when manually registering the capability:
41
+ @integration.register_capability(StandardCapabilityName.VALIDATE_CREDENTIAL_CONFIG)
42
+ async def validate_credential_config(
43
+ args: ValidateCredentialConfigRequest,
44
+ ) -> ValidateCredentialConfigResponse:
45
+ # Use base validation
46
+ errors = CredentialsModule.base_validation(integration, args)
47
+ if errors:
48
+ return ValidateCredentialConfigResponse(response=ValidatedCredentialConfig(valid=False, errors=errors))
49
+ # Add custom validation logic here
50
+ # ...
51
+ return ValidateCredentialConfigResponse(response=ValidatedCredentialConfig(valid=True))
52
+ """
53
+
54
+ credentials: dict[str, CredentialConfig]
55
+ settings: CredentialsSettings
56
+
57
+ def __init__(self, settings: CredentialsSettings):
58
+ super().__init__()
59
+ self.credentials = {}
60
+ self.settings = settings
61
+
62
+ def add_capability(self, capability: str):
63
+ """Add a capability to the module."""
64
+ self.capabilities.append(capability)
65
+
66
+ def get_capability(self, capability: str) -> StandardCapabilityName | str | None:
67
+ """Get a capability from the module."""
68
+ for cap in self.capabilities:
69
+ if cap == capability:
70
+ return cap
71
+ return None
72
+
73
+ def register(self, integration: "Integration"):
74
+ """Register validate_credential_config capability for each credential config."""
75
+ self.integration = integration
76
+ validation_functions: dict[str, ValidateCredentialConfigCallable] = {}
77
+
78
+ for credential in integration.credentials:
79
+ self.credentials[credential.id] = credential
80
+ validation_implementation = credential.validation
81
+ if validation_implementation:
82
+ validation_functions[credential.id] = cast(
83
+ ValidateCredentialConfigCallable, validation_implementation
84
+ )
85
+
86
+ if self.settings.register_validation_capability and (
87
+ StandardCapabilityName.VALIDATE_CREDENTIAL_CONFIG.value
88
+ not in self.integration.capabilities.keys()
89
+ ):
90
+ """
91
+ If the Integration already registers a validate_credential_config capability,
92
+ we don't register another one, as it would be a duplicate.
93
+ """
94
+ self.register_dynamic_validation_capability(
95
+ StandardCapabilityName.VALIDATE_CREDENTIAL_CONFIG,
96
+ validation_functions,
97
+ )
98
+
99
+ def register_dynamic_validation_capability(
100
+ self,
101
+ capability_name: StandardCapabilityName,
102
+ validation_functions: dict[str, ValidateCredentialConfigCallable],
103
+ ):
104
+ @self.integration.register_capability(capability_name)
105
+ async def validate_credential_config(
106
+ args: ValidateCredentialConfigRequest,
107
+ ) -> ValidateCredentialConfigResponse:
108
+ is_valid = False
109
+ errors = CredentialsModule.base_validation(
110
+ self.integration.app_id, self.integration.credentials, args
111
+ )
112
+
113
+ if errors:
114
+ return ValidateCredentialConfigResponse(
115
+ response=ValidatedCredentialConfig(
116
+ valid=is_valid,
117
+ validation_errors=errors,
118
+ ),
119
+ )
120
+
121
+ for credential_id, validation_function in validation_functions.items():
122
+ if credential_id != args.request.credential.id:
123
+ # Skip validation for non-received credentials
124
+ continue
125
+
126
+ """
127
+ If this raises, it will bubble up just like any other capability error.
128
+ """
129
+ result = validation_function(args)
130
+ if inspect.isawaitable(result):
131
+ result = await cast(
132
+ Awaitable[ValidateCredentialConfigResponse | ErrorResponse],
133
+ result,
134
+ )
135
+
136
+ if isinstance(result, ErrorResponse):
137
+ raise CapabilityExecutionError(result)
138
+
139
+ if isinstance(result, ValidateCredentialConfigResponse):
140
+ if not result.response.valid or result.response.validation_errors:
141
+ errors.extend(result.response.validation_errors or [])
142
+
143
+ if not result.response.valid and not result.response.validation_errors:
144
+ errors.append("Credential is invalid, unexpected error occurred")
145
+
146
+ if not errors:
147
+ is_valid = True
148
+
149
+ return ValidateCredentialConfigResponse(
150
+ response=ValidatedCredentialConfig(
151
+ valid=is_valid,
152
+ validation_errors=errors,
153
+ ),
154
+ )
155
+
156
+ return validate_credential_config
157
+
158
+ # Utility methods
159
+
160
+ @classmethod
161
+ def base_validation(
162
+ cls,
163
+ app_id: str,
164
+ credentials: Sequence[CredentialConfig | OAuthConfig],
165
+ request: ValidateCredentialConfigRequest,
166
+ ) -> list[str]:
167
+ """
168
+ Perform base validation on a credential config request.
169
+
170
+ This method can be called as a class method to reuse the base validation logic
171
+ when manually implementing the validate_credential_config capability.
172
+
173
+ Example usage when manually registering the capability:
174
+ @integration.register_capability(StandardCapabilityName.VALIDATE_CREDENTIAL_CONFIG)
175
+ async def validate_credential_config(
176
+ args: ValidateCredentialConfigRequest,
177
+ ) -> ValidateCredentialConfigResponse:
178
+ # Use base validation
179
+ errors = CredentialsModule.base_validation("app_id", CredentialConfigList, args)
180
+ if errors:
181
+ return ValidateCredentialConfigResponse(
182
+ response=ValidatedCredentialConfig(valid=False, validation_errors=errors)
183
+ )
184
+ # Add custom validation logic here
185
+ # ...
186
+ return ValidateCredentialConfigResponse(
187
+ response=ValidatedCredentialConfig(valid=True, validation_errors=[])
188
+ )
189
+
190
+ Args:
191
+ app_id: The App ID of the integration
192
+ credentials: The credentials (configs) to validate against
193
+ request: The validation request to validate
194
+
195
+ Returns:
196
+ A list of error messages (empty if validation passes)
197
+
198
+ Raises:
199
+ CapabilityExecutionError: For critical validation failures (missing ID, invalid config, etc.)
200
+ """
201
+ errors: list[str] = [] # Customer facing errors
202
+ credential_config_id = request.request.credential.id
203
+ credential = request.request.credential
204
+ credential_dict = credential.model_dump()
205
+
206
+ if not credential_config_id:
207
+ # This should not happen, and should in such case fail immediately
208
+ raise CapabilityExecutionError(
209
+ ErrorResponse(
210
+ is_error=True,
211
+ error=Error(
212
+ error_code=ErrorCode.BAD_REQUEST,
213
+ message="Received credential without an ID",
214
+ app_id=app_id,
215
+ ),
216
+ )
217
+ )
218
+
219
+ # Build credentials dict from integration.credentials
220
+ credentials_dict = {cred.id: cred for cred in credentials}
221
+ credential_config = credentials_dict.get(credential_config_id)
222
+
223
+ if credential_config is None:
224
+ # Should fail fast
225
+ raise CapabilityExecutionError(
226
+ ErrorResponse(
227
+ is_error=True,
228
+ error=Error(
229
+ error_code=ErrorCode.BAD_REQUEST,
230
+ message=f"Missing credential configuration for ID {credential_config_id}",
231
+ app_id=app_id,
232
+ ),
233
+ )
234
+ )
235
+
236
+ try:
237
+ from connector.oai.integration import AUTH_TYPE_MAP
238
+
239
+ credential_model = AUTH_TYPE_MAP[credential_config.type](
240
+ **credential_dict[credential_config.type]
241
+ )
242
+ connector_credential = credential_model.model_validate(credential_model)
243
+ except ValidationError as e:
244
+ raise CapabilityExecutionError(
245
+ ErrorResponse(
246
+ is_error=True,
247
+ error=Error(
248
+ error_code=ErrorCode.BAD_REQUEST,
249
+ message="Invalid or malformed credential received",
250
+ app_id=app_id,
251
+ ),
252
+ )
253
+ ) from e
254
+
255
+ # Dump the model
256
+ credential_dict = connector_credential.model_dump(exclude_none=True)
257
+
258
+ # Check for empty models
259
+ if credential_dict == {}:
260
+ errors.append("Credential is missing required fields")
261
+ return errors
262
+
263
+ # Get the list of required fields from the model's JSON schema
264
+ model_schema = credential_model.model_json_schema()
265
+ required_fields = set(model_schema.get("required", []))
266
+
267
+ # Check for empty strings on required fields
268
+ for field_name, value in credential_dict.items():
269
+ if field_name in required_fields and value == "":
270
+ errors.append(
271
+ "A required field is empty, please provide a value before submitting again"
272
+ )
273
+ return errors
274
+
275
+ # Check for extra whitespace
276
+ if any(value.strip() != value for value in credential_dict.values()):
277
+ errors.append(
278
+ "Credential has extra whitespace, please remove it before submitting it again"
279
+ )
280
+ return errors
281
+
282
+ return errors