mergepythonclient 0.0.1__py3-none-any.whl

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 (834) hide show
  1. merge/__init__.py +77 -0
  2. merge/_base_client.py +1431 -0
  3. merge/_base_exceptions.py +117 -0
  4. merge/_client.py +344 -0
  5. merge/_exceptions.py +31 -0
  6. merge/_models.py +235 -0
  7. merge/_qs.py +148 -0
  8. merge/_resource.py +34 -0
  9. merge/_types.py +145 -0
  10. merge/_utils/__init__.py +25 -0
  11. merge/_utils/_transform.py +205 -0
  12. merge/_utils/_utils.py +325 -0
  13. merge/_version.py +4 -0
  14. merge/pagination.py +43 -0
  15. merge/py.typed +0 -0
  16. merge/resources/__init__.py +26 -0
  17. merge/resources/accounting/__init__.py +104 -0
  18. merge/resources/accounting/account_details.py +52 -0
  19. merge/resources/accounting/account_tokens.py +54 -0
  20. merge/resources/accounting/accounting.py +184 -0
  21. merge/resources/accounting/accounts/__init__.py +6 -0
  22. merge/resources/accounting/accounts/accounts.py +428 -0
  23. merge/resources/accounting/accounts/meta.py +52 -0
  24. merge/resources/accounting/addresses.py +122 -0
  25. merge/resources/accounting/attachments/__init__.py +6 -0
  26. merge/resources/accounting/attachments/attachments.py +371 -0
  27. merge/resources/accounting/attachments/meta.py +52 -0
  28. merge/resources/accounting/available_actions.py +52 -0
  29. merge/resources/accounting/balance_sheets.py +294 -0
  30. merge/resources/accounting/cash_flow_statements.py +294 -0
  31. merge/resources/accounting/common_model_scopes.py +185 -0
  32. merge/resources/accounting/company_info.py +286 -0
  33. merge/resources/accounting/contacts/__init__.py +6 -0
  34. merge/resources/accounting/contacts/contacts.py +428 -0
  35. merge/resources/accounting/contacts/meta.py +52 -0
  36. merge/resources/accounting/credit_notes.py +342 -0
  37. merge/resources/accounting/expenses/__init__.py +6 -0
  38. merge/resources/accounting/expenses/expenses.py +416 -0
  39. merge/resources/accounting/expenses/meta.py +52 -0
  40. merge/resources/accounting/income_statements.py +294 -0
  41. merge/resources/accounting/invoices/__init__.py +6 -0
  42. merge/resources/accounting/invoices/invoices.py +472 -0
  43. merge/resources/accounting/invoices/meta.py +52 -0
  44. merge/resources/accounting/issues.py +251 -0
  45. merge/resources/accounting/items.py +322 -0
  46. merge/resources/accounting/journal_entries/__init__.py +6 -0
  47. merge/resources/accounting/journal_entries/journal_entries.py +416 -0
  48. merge/resources/accounting/journal_entries/meta.py +52 -0
  49. merge/resources/accounting/link_tokens.py +173 -0
  50. merge/resources/accounting/linked_accounts.py +286 -0
  51. merge/resources/accounting/passthrough_requests.py +167 -0
  52. merge/resources/accounting/payments/__init__.py +6 -0
  53. merge/resources/accounting/payments/meta.py +52 -0
  54. merge/resources/accounting/payments/payments.py +430 -0
  55. merge/resources/accounting/phone_numbers.py +97 -0
  56. merge/resources/accounting/purchase_orders/__init__.py +6 -0
  57. merge/resources/accounting/purchase_orders/meta.py +52 -0
  58. merge/resources/accounting/purchase_orders/purchase_orders.py +452 -0
  59. merge/resources/accounting/remote_keys.py +144 -0
  60. merge/resources/accounting/selective_sync.py +234 -0
  61. merge/resources/accounting/sync_status.py +167 -0
  62. merge/resources/accounting/tax_rates.py +290 -0
  63. merge/resources/accounting/tracking_categories.py +326 -0
  64. merge/resources/accounting/transactions.py +310 -0
  65. merge/resources/accounting/vendor_credits.py +310 -0
  66. merge/resources/accounting/webhook_receivers.py +139 -0
  67. merge/resources/ats/__init__.py +89 -0
  68. merge/resources/ats/account_details.py +52 -0
  69. merge/resources/ats/account_tokens.py +54 -0
  70. merge/resources/ats/activities/__init__.py +6 -0
  71. merge/resources/ats/activities/activities.py +446 -0
  72. merge/resources/ats/activities/meta.py +52 -0
  73. merge/resources/ats/applications/__init__.py +6 -0
  74. merge/resources/ats/applications/applications.py +547 -0
  75. merge/resources/ats/applications/meta.py +96 -0
  76. merge/resources/ats/ats.py +159 -0
  77. merge/resources/ats/attachments/__init__.py +6 -0
  78. merge/resources/ats/attachments/attachments.py +442 -0
  79. merge/resources/ats/attachments/meta.py +52 -0
  80. merge/resources/ats/available_actions.py +52 -0
  81. merge/resources/ats/candidates/__init__.py +6 -0
  82. merge/resources/ats/candidates/candidates.py +543 -0
  83. merge/resources/ats/candidates/meta.py +52 -0
  84. merge/resources/ats/common_model_scopes.py +185 -0
  85. merge/resources/ats/departments.py +255 -0
  86. merge/resources/ats/eeocs.py +458 -0
  87. merge/resources/ats/interviews/__init__.py +6 -0
  88. merge/resources/ats/interviews/interviews.py +464 -0
  89. merge/resources/ats/interviews/meta.py +52 -0
  90. merge/resources/ats/issues.py +251 -0
  91. merge/resources/ats/job_interview_stages.py +294 -0
  92. merge/resources/ats/jobs.py +354 -0
  93. merge/resources/ats/link_tokens.py +173 -0
  94. merge/resources/ats/linked_accounts.py +286 -0
  95. merge/resources/ats/offers.py +330 -0
  96. merge/resources/ats/offices.py +255 -0
  97. merge/resources/ats/passthrough_requests.py +167 -0
  98. merge/resources/ats/reject_reasons.py +261 -0
  99. merge/resources/ats/remote_keys.py +144 -0
  100. merge/resources/ats/scorecards.py +338 -0
  101. merge/resources/ats/selective_sync.py +234 -0
  102. merge/resources/ats/sync_status.py +167 -0
  103. merge/resources/ats/tags.py +174 -0
  104. merge/resources/ats/users.py +303 -0
  105. merge/resources/ats/webhook_receivers.py +136 -0
  106. merge/resources/crm/__init__.py +80 -0
  107. merge/resources/crm/account_details.py +52 -0
  108. merge/resources/crm/account_tokens.py +54 -0
  109. merge/resources/crm/accounts/__init__.py +6 -0
  110. merge/resources/crm/accounts/accounts.py +626 -0
  111. merge/resources/crm/accounts/meta.py +92 -0
  112. merge/resources/crm/available_actions.py +52 -0
  113. merge/resources/crm/common_model_scopes.py +185 -0
  114. merge/resources/crm/contacts/__init__.py +6 -0
  115. merge/resources/crm/contacts/contacts.py +727 -0
  116. merge/resources/crm/contacts/meta.py +92 -0
  117. merge/resources/crm/crm.py +144 -0
  118. merge/resources/crm/custom_object_classes/__init__.py +6 -0
  119. merge/resources/crm/custom_object_classes/association_types/__init__.py +6 -0
  120. merge/resources/crm/custom_object_classes/association_types/association_types.py +374 -0
  121. merge/resources/crm/custom_object_classes/association_types/meta.py +54 -0
  122. merge/resources/crm/custom_object_classes/custom_object_classes.py +302 -0
  123. merge/resources/crm/custom_objects/__init__.py +17 -0
  124. merge/resources/crm/custom_objects/associations.py +250 -0
  125. merge/resources/crm/custom_objects/custom_objects.py +452 -0
  126. merge/resources/crm/custom_objects/generators.py +54 -0
  127. merge/resources/crm/custom_objects/meta.py +96 -0
  128. merge/resources/crm/engagement_types.py +409 -0
  129. merge/resources/crm/engagements/__init__.py +6 -0
  130. merge/resources/crm/engagements/engagements.py +623 -0
  131. merge/resources/crm/engagements/meta.py +92 -0
  132. merge/resources/crm/issues.py +251 -0
  133. merge/resources/crm/leads/__init__.py +6 -0
  134. merge/resources/crm/leads/leads.py +558 -0
  135. merge/resources/crm/leads/meta.py +52 -0
  136. merge/resources/crm/link_tokens.py +173 -0
  137. merge/resources/crm/linked_accounts.py +286 -0
  138. merge/resources/crm/notes/__init__.py +6 -0
  139. merge/resources/crm/notes/meta.py +52 -0
  140. merge/resources/crm/notes/notes.py +564 -0
  141. merge/resources/crm/opportunities/__init__.py +6 -0
  142. merge/resources/crm/opportunities/meta.py +92 -0
  143. merge/resources/crm/opportunities/opportunities.py +697 -0
  144. merge/resources/crm/passthrough_requests.py +167 -0
  145. merge/resources/crm/remote_keys.py +144 -0
  146. merge/resources/crm/selective_sync.py +234 -0
  147. merge/resources/crm/stages.py +409 -0
  148. merge/resources/crm/sync_status.py +167 -0
  149. merge/resources/crm/tasks/__init__.py +6 -0
  150. merge/resources/crm/tasks/meta.py +92 -0
  151. merge/resources/crm/tasks/tasks.py +619 -0
  152. merge/resources/crm/users.py +509 -0
  153. merge/resources/crm/webhook_receivers.py +136 -0
  154. merge/resources/file_storage/__init__.py +59 -0
  155. merge/resources/file_storage/account_details.py +52 -0
  156. merge/resources/file_storage/account_tokens.py +54 -0
  157. merge/resources/file_storage/available_actions.py +52 -0
  158. merge/resources/file_storage/common_model_scopes.py +185 -0
  159. merge/resources/file_storage/drives.py +265 -0
  160. merge/resources/file_storage/file_storage.py +109 -0
  161. merge/resources/file_storage/files/__init__.py +6 -0
  162. merge/resources/file_storage/files/files.py +452 -0
  163. merge/resources/file_storage/files/meta.py +52 -0
  164. merge/resources/file_storage/folders/__init__.py +6 -0
  165. merge/resources/file_storage/folders/folders.py +420 -0
  166. merge/resources/file_storage/folders/meta.py +52 -0
  167. merge/resources/file_storage/groups.py +255 -0
  168. merge/resources/file_storage/issues.py +251 -0
  169. merge/resources/file_storage/link_tokens.py +173 -0
  170. merge/resources/file_storage/linked_accounts.py +286 -0
  171. merge/resources/file_storage/passthrough_requests.py +167 -0
  172. merge/resources/file_storage/remote_keys.py +147 -0
  173. merge/resources/file_storage/selective_sync.py +234 -0
  174. merge/resources/file_storage/sync_status.py +167 -0
  175. merge/resources/file_storage/users.py +255 -0
  176. merge/resources/file_storage/webhook_receivers.py +139 -0
  177. merge/resources/hris/__init__.py +83 -0
  178. merge/resources/hris/account_details.py +52 -0
  179. merge/resources/hris/account_tokens.py +54 -0
  180. merge/resources/hris/available_actions.py +52 -0
  181. merge/resources/hris/banks.py +356 -0
  182. merge/resources/hris/benefits.py +290 -0
  183. merge/resources/hris/common_model_scopes.py +185 -0
  184. merge/resources/hris/companies.py +255 -0
  185. merge/resources/hris/employee_payroll_runs.py +336 -0
  186. merge/resources/hris/employees/__init__.py +6 -0
  187. merge/resources/hris/employees/employees.py +841 -0
  188. merge/resources/hris/employees/meta.py +52 -0
  189. merge/resources/hris/employments.py +466 -0
  190. merge/resources/hris/groups.py +304 -0
  191. merge/resources/hris/hris.py +149 -0
  192. merge/resources/hris/issues.py +251 -0
  193. merge/resources/hris/link_tokens.py +173 -0
  194. merge/resources/hris/linked_accounts.py +286 -0
  195. merge/resources/hris/locations.py +294 -0
  196. merge/resources/hris/passthrough_requests.py +167 -0
  197. merge/resources/hris/pay_groups.py +255 -0
  198. merge/resources/hris/payroll_runs.py +356 -0
  199. merge/resources/hris/remote_keys.py +144 -0
  200. merge/resources/hris/selective_sync.py +234 -0
  201. merge/resources/hris/sync_status.py +167 -0
  202. merge/resources/hris/teams.py +291 -0
  203. merge/resources/hris/time_off/__init__.py +6 -0
  204. merge/resources/hris/time_off/meta.py +52 -0
  205. merge/resources/hris/time_off/time_off.py +560 -0
  206. merge/resources/hris/time_off_balances.py +354 -0
  207. merge/resources/hris/webhook_receivers.py +136 -0
  208. merge/resources/marketing/__init__.py +74 -0
  209. merge/resources/marketing/account_details.py +52 -0
  210. merge/resources/marketing/account_tokens.py +54 -0
  211. merge/resources/marketing/actions/__init__.py +6 -0
  212. merge/resources/marketing/actions/actions.py +363 -0
  213. merge/resources/marketing/actions/meta.py +52 -0
  214. merge/resources/marketing/automations/__init__.py +6 -0
  215. merge/resources/marketing/automations/automations.py +481 -0
  216. merge/resources/marketing/automations/meta.py +52 -0
  217. merge/resources/marketing/available_actions.py +52 -0
  218. merge/resources/marketing/campaigns/__init__.py +6 -0
  219. merge/resources/marketing/campaigns/campaigns.py +481 -0
  220. merge/resources/marketing/campaigns/meta.py +52 -0
  221. merge/resources/marketing/common_model_scopes.py +185 -0
  222. merge/resources/marketing/contact_lists/__init__.py +6 -0
  223. merge/resources/marketing/contact_lists/contact_lists.py +477 -0
  224. merge/resources/marketing/contact_lists/meta.py +52 -0
  225. merge/resources/marketing/contacts/__init__.py +6 -0
  226. merge/resources/marketing/contacts/contacts.py +361 -0
  227. merge/resources/marketing/contacts/meta.py +52 -0
  228. merge/resources/marketing/emails.py +375 -0
  229. merge/resources/marketing/events.py +375 -0
  230. merge/resources/marketing/issues.py +251 -0
  231. merge/resources/marketing/link_tokens.py +173 -0
  232. merge/resources/marketing/linked_accounts.py +286 -0
  233. merge/resources/marketing/marketing.py +134 -0
  234. merge/resources/marketing/messages.py +375 -0
  235. merge/resources/marketing/passthrough_requests.py +167 -0
  236. merge/resources/marketing/remote_keys.py +144 -0
  237. merge/resources/marketing/selective_sync.py +234 -0
  238. merge/resources/marketing/sync_status.py +167 -0
  239. merge/resources/marketing/templates/__init__.py +6 -0
  240. merge/resources/marketing/templates/meta.py +52 -0
  241. merge/resources/marketing/templates/templates.py +365 -0
  242. merge/resources/marketing/users.py +255 -0
  243. merge/resources/marketing/webhook_receivers.py +139 -0
  244. merge/resources/ticketing/__init__.py +74 -0
  245. merge/resources/ticketing/account_details.py +52 -0
  246. merge/resources/ticketing/account_tokens.py +54 -0
  247. merge/resources/ticketing/accounts.py +256 -0
  248. merge/resources/ticketing/attachments/__init__.py +6 -0
  249. merge/resources/ticketing/attachments/attachments.py +396 -0
  250. merge/resources/ticketing/attachments/meta.py +52 -0
  251. merge/resources/ticketing/available_actions.py +52 -0
  252. merge/resources/ticketing/collections.py +468 -0
  253. merge/resources/ticketing/comments/__init__.py +6 -0
  254. merge/resources/ticketing/comments/comments.py +396 -0
  255. merge/resources/ticketing/comments/meta.py +52 -0
  256. merge/resources/ticketing/common_model_scopes.py +185 -0
  257. merge/resources/ticketing/contacts.py +283 -0
  258. merge/resources/ticketing/issues.py +251 -0
  259. merge/resources/ticketing/link_tokens.py +173 -0
  260. merge/resources/ticketing/linked_accounts.py +286 -0
  261. merge/resources/ticketing/passthrough_requests.py +167 -0
  262. merge/resources/ticketing/projects.py +386 -0
  263. merge/resources/ticketing/remote_keys.py +144 -0
  264. merge/resources/ticketing/selective_sync.py +234 -0
  265. merge/resources/ticketing/sync_status.py +167 -0
  266. merge/resources/ticketing/tags.py +256 -0
  267. merge/resources/ticketing/teams.py +256 -0
  268. merge/resources/ticketing/ticketing.py +134 -0
  269. merge/resources/ticketing/tickets/__init__.py +6 -0
  270. merge/resources/ticketing/tickets/meta.py +92 -0
  271. merge/resources/ticketing/tickets/tickets.py +1037 -0
  272. merge/resources/ticketing/users.py +292 -0
  273. merge/resources/ticketing/webhook_receivers.py +139 -0
  274. merge/types/__init__.py +33 -0
  275. merge/types/accounting/__init__.py +155 -0
  276. merge/types/accounting/account_create_params.py +706 -0
  277. merge/types/accounting/account_list_params.py +63 -0
  278. merge/types/accounting/account_response.py +28 -0
  279. merge/types/accounting/account_retrieve_params.py +28 -0
  280. merge/types/accounting/accounting_attachment.py +35 -0
  281. merge/types/accounting/accounting_attachment_response.py +30 -0
  282. merge/types/accounting/accounts/__init__.py +3 -0
  283. merge/types/accounting/address_retrieve_params.py +21 -0
  284. merge/types/accounting/attachment_create_params.py +38 -0
  285. merge/types/accounting/attachment_list_params.py +51 -0
  286. merge/types/accounting/attachment_retrieve_params.py +15 -0
  287. merge/types/accounting/attachments/__init__.py +3 -0
  288. merge/types/accounting/balance_sheet.py +728 -0
  289. merge/types/accounting/balance_sheet_list_params.py +57 -0
  290. merge/types/accounting/balance_sheet_retrieve_params.py +22 -0
  291. merge/types/accounting/cash_flow_statement.py +730 -0
  292. merge/types/accounting/cash_flow_statement_list_params.py +57 -0
  293. merge/types/accounting/cash_flow_statement_retrieve_params.py +22 -0
  294. merge/types/accounting/common_model_scope_retrieve_params.py +12 -0
  295. merge/types/accounting/common_model_scope_update_params.py +21 -0
  296. merge/types/accounting/company_info.py +672 -0
  297. merge/types/accounting/company_info_list_params.py +54 -0
  298. merge/types/accounting/company_info_retrieve_params.py +22 -0
  299. merge/types/accounting/contact_create_params.py +384 -0
  300. merge/types/accounting/contact_list_params.py +63 -0
  301. merge/types/accounting/contact_response.py +28 -0
  302. merge/types/accounting/contact_retrieve_params.py +28 -0
  303. merge/types/accounting/contacts/__init__.py +3 -0
  304. merge/types/accounting/credit_note.py +727 -0
  305. merge/types/accounting/credit_note_list_params.py +69 -0
  306. merge/types/accounting/credit_note_retrieve_params.py +28 -0
  307. merge/types/accounting/expense.py +707 -0
  308. merge/types/accounting/expense_create_params.py +709 -0
  309. merge/types/accounting/expense_list_params.py +63 -0
  310. merge/types/accounting/expense_response.py +31 -0
  311. merge/types/accounting/expense_retrieve_params.py +22 -0
  312. merge/types/accounting/expenses/__init__.py +3 -0
  313. merge/types/accounting/income_statement.py +751 -0
  314. merge/types/accounting/income_statement_list_params.py +57 -0
  315. merge/types/accounting/income_statement_retrieve_params.py +22 -0
  316. merge/types/accounting/invoice.py +1357 -0
  317. merge/types/accounting/invoice_create_params.py +1351 -0
  318. merge/types/accounting/invoice_list_params.py +79 -0
  319. merge/types/accounting/invoice_response.py +30 -0
  320. merge/types/accounting/invoice_retrieve_params.py +28 -0
  321. merge/types/accounting/invoices/__init__.py +3 -0
  322. merge/types/accounting/issue_list_params.py +72 -0
  323. merge/types/accounting/item.py +54 -0
  324. merge/types/accounting/item_list_params.py +63 -0
  325. merge/types/accounting/item_retrieve_params.py +28 -0
  326. merge/types/accounting/journal_entries/__init__.py +3 -0
  327. merge/types/accounting/journal_entry.py +701 -0
  328. merge/types/accounting/journal_entry_create_params.py +699 -0
  329. merge/types/accounting/journal_entry_list_params.py +63 -0
  330. merge/types/accounting/journal_entry_response.py +31 -0
  331. merge/types/accounting/journal_entry_retrieve_params.py +22 -0
  332. merge/types/accounting/link_token_create_params.py +66 -0
  333. merge/types/accounting/linked_account_list_params.py +89 -0
  334. merge/types/accounting/passthrough_request_send_params.py +76 -0
  335. merge/types/accounting/payment.py +669 -0
  336. merge/types/accounting/payment_create_params.py +669 -0
  337. merge/types/accounting/payment_list_params.py +69 -0
  338. merge/types/accounting/payment_response.py +30 -0
  339. merge/types/accounting/payment_retrieve_params.py +22 -0
  340. merge/types/accounting/payments/__init__.py +3 -0
  341. merge/types/accounting/phone_number.py +19 -0
  342. merge/types/accounting/phone_number_retrieve_params.py +15 -0
  343. merge/types/accounting/purchase_order.py +1351 -0
  344. merge/types/accounting/purchase_order_create_params.py +1346 -0
  345. merge/types/accounting/purchase_order_list_params.py +69 -0
  346. merge/types/accounting/purchase_order_response.py +31 -0
  347. merge/types/accounting/purchase_order_retrieve_params.py +28 -0
  348. merge/types/accounting/purchase_orders/__init__.py +3 -0
  349. merge/types/accounting/remote_key_generate_params.py +11 -0
  350. merge/types/accounting/remote_key_regenerate_params.py +11 -0
  351. merge/types/accounting/selective_sync_list_configurations_response.py +11 -0
  352. merge/types/accounting/selective_sync_list_metadata_params.py +17 -0
  353. merge/types/accounting/selective_sync_replace_configurations_params.py +29 -0
  354. merge/types/accounting/selective_sync_replace_configurations_response.py +11 -0
  355. merge/types/accounting/sync_status_list_params.py +15 -0
  356. merge/types/accounting/sync_status_resync_response.py +9 -0
  357. merge/types/accounting/tax_rate.py +38 -0
  358. merge/types/accounting/tax_rate_list_params.py +57 -0
  359. merge/types/accounting/tax_rate_retrieve_params.py +22 -0
  360. merge/types/accounting/tracking_category.py +48 -0
  361. merge/types/accounting/tracking_category_list_params.py +63 -0
  362. merge/types/accounting/tracking_category_retrieve_params.py +28 -0
  363. merge/types/accounting/transaction.py +1336 -0
  364. merge/types/accounting/transaction_list_params.py +63 -0
  365. merge/types/accounting/transaction_retrieve_params.py +22 -0
  366. merge/types/accounting/vendor_credit.py +697 -0
  367. merge/types/accounting/vendor_credit_list_params.py +63 -0
  368. merge/types/accounting/vendor_credit_retrieve_params.py +22 -0
  369. merge/types/accounting/webhook_receiver_create_params.py +15 -0
  370. merge/types/accounting/webhook_receiver_list_response.py +9 -0
  371. merge/types/ats/__init__.py +125 -0
  372. merge/types/ats/activities/__init__.py +3 -0
  373. merge/types/ats/activity.py +53 -0
  374. merge/types/ats/activity_create_params.py +55 -0
  375. merge/types/ats/activity_create_response.py +31 -0
  376. merge/types/ats/activity_list_params.py +63 -0
  377. merge/types/ats/activity_retrieve_params.py +28 -0
  378. merge/types/ats/application.py +49 -0
  379. merge/types/ats/application_change_stage_params.py +15 -0
  380. merge/types/ats/application_create_params.py +63 -0
  381. merge/types/ats/application_list_params.py +72 -0
  382. merge/types/ats/application_response.py +33 -0
  383. merge/types/ats/application_retrieve_params.py +22 -0
  384. merge/types/ats/applications/__init__.py +5 -0
  385. merge/types/ats/applications/meta_for_create_params.py +12 -0
  386. merge/types/ats/attachment_create_params.py +61 -0
  387. merge/types/ats/attachment_list_params.py +63 -0
  388. merge/types/ats/attachment_response.py +28 -0
  389. merge/types/ats/attachment_retrieve_params.py +28 -0
  390. merge/types/ats/attachments/__init__.py +3 -0
  391. merge/types/ats/candidate.py +128 -0
  392. merge/types/ats/candidate_create_params.py +137 -0
  393. merge/types/ats/candidate_ignore_row_params.py +18 -0
  394. merge/types/ats/candidate_list_params.py +72 -0
  395. merge/types/ats/candidate_response.py +32 -0
  396. merge/types/ats/candidate_retrieve_params.py +22 -0
  397. merge/types/ats/candidates/__init__.py +3 -0
  398. merge/types/ats/common_model_scope_retrieve_params.py +12 -0
  399. merge/types/ats/common_model_scope_update_params.py +21 -0
  400. merge/types/ats/department.py +29 -0
  401. merge/types/ats/department_list_params.py +48 -0
  402. merge/types/ats/department_retrieve_params.py +15 -0
  403. merge/types/ats/eeoc.py +94 -0
  404. merge/types/ats/eeoc_list_params.py +95 -0
  405. merge/types/ats/eeoc_retrieve_params.py +60 -0
  406. merge/types/ats/interview_create_params.py +64 -0
  407. merge/types/ats/interview_list_params.py +69 -0
  408. merge/types/ats/interview_retrieve_params.py +28 -0
  409. merge/types/ats/interviews/__init__.py +3 -0
  410. merge/types/ats/issue_list_params.py +72 -0
  411. merge/types/ats/job.py +91 -0
  412. merge/types/ats/job_interview_stage.py +35 -0
  413. merge/types/ats/job_interview_stage_list_params.py +57 -0
  414. merge/types/ats/job_interview_stage_retrieve_params.py +22 -0
  415. merge/types/ats/job_list_params.py +81 -0
  416. merge/types/ats/job_retrieve_params.py +28 -0
  417. merge/types/ats/link_token_create_params.py +66 -0
  418. merge/types/ats/linked_account_list_params.py +89 -0
  419. merge/types/ats/offer.py +62 -0
  420. merge/types/ats/offer_list_params.py +66 -0
  421. merge/types/ats/offer_retrieve_params.py +28 -0
  422. merge/types/ats/office.py +32 -0
  423. merge/types/ats/office_list_params.py +48 -0
  424. merge/types/ats/office_retrieve_params.py +15 -0
  425. merge/types/ats/passthrough_request_send_params.py +76 -0
  426. merge/types/ats/reject_reason.py +29 -0
  427. merge/types/ats/reject_reason_list_params.py +48 -0
  428. merge/types/ats/reject_reason_retrieve_params.py +15 -0
  429. merge/types/ats/remote_key_generate_params.py +11 -0
  430. merge/types/ats/remote_key_regenerate_params.py +11 -0
  431. merge/types/ats/scheduled_interview.py +61 -0
  432. merge/types/ats/scheduled_interview_response.py +32 -0
  433. merge/types/ats/scorecard.py +51 -0
  434. merge/types/ats/scorecard_list_params.py +69 -0
  435. merge/types/ats/scorecard_retrieve_params.py +28 -0
  436. merge/types/ats/selective_sync_list_configurations_response.py +11 -0
  437. merge/types/ats/selective_sync_list_metadata_params.py +17 -0
  438. merge/types/ats/selective_sync_replace_configurations_params.py +29 -0
  439. merge/types/ats/selective_sync_replace_configurations_response.py +11 -0
  440. merge/types/ats/sync_status_list_params.py +15 -0
  441. merge/types/ats/sync_status_resync_response.py +9 -0
  442. merge/types/ats/tag_list_params.py +48 -0
  443. merge/types/ats/user_list_params.py +57 -0
  444. merge/types/ats/user_retrieve_params.py +21 -0
  445. merge/types/ats/webhook_receiver_create_params.py +15 -0
  446. merge/types/ats/webhook_receiver_list_response.py +9 -0
  447. merge/types/crm/__init__.py +156 -0
  448. merge/types/crm/account_create_params.py +706 -0
  449. merge/types/crm/account_list_params.py +63 -0
  450. merge/types/crm/account_list_remote_field_classes_params.py +30 -0
  451. merge/types/crm/account_response.py +28 -0
  452. merge/types/crm/account_retrieve_params.py +28 -0
  453. merge/types/crm/account_update_params.py +55 -0
  454. merge/types/crm/accounts/__init__.py +3 -0
  455. merge/types/crm/common_model_scope_retrieve_params.py +12 -0
  456. merge/types/crm/common_model_scope_update_params.py +21 -0
  457. merge/types/crm/contact_create_params.py +384 -0
  458. merge/types/crm/contact_ignore_row_params.py +18 -0
  459. merge/types/crm/contact_list_params.py +63 -0
  460. merge/types/crm/contact_list_remote_field_classes_params.py +30 -0
  461. merge/types/crm/contact_response.py +28 -0
  462. merge/types/crm/contact_retrieve_params.py +28 -0
  463. merge/types/crm/contact_update_params.py +371 -0
  464. merge/types/crm/contacts/__init__.py +3 -0
  465. merge/types/crm/custom_object.py +31 -0
  466. merge/types/crm/custom_object_class.py +73 -0
  467. merge/types/crm/custom_object_class_list_params.py +54 -0
  468. merge/types/crm/custom_object_class_retrieve_params.py +22 -0
  469. merge/types/crm/custom_object_classes/__init__.py +17 -0
  470. merge/types/crm/custom_object_classes/association_type.py +46 -0
  471. merge/types/crm/custom_object_classes/association_type_create_params.py +54 -0
  472. merge/types/crm/custom_object_classes/association_type_list_params.py +54 -0
  473. merge/types/crm/custom_object_classes/association_type_response.py +29 -0
  474. merge/types/crm/custom_object_classes/association_type_retrieve_params.py +22 -0
  475. merge/types/crm/custom_object_classes/association_types/__init__.py +3 -0
  476. merge/types/crm/custom_object_create_params.py +15 -0
  477. merge/types/crm/custom_object_list_params.py +54 -0
  478. merge/types/crm/custom_object_response.py +29 -0
  479. merge/types/crm/custom_object_retrieve_params.py +21 -0
  480. merge/types/crm/custom_object_update_params.py +15 -0
  481. merge/types/crm/custom_objects/__init__.py +6 -0
  482. merge/types/crm/custom_objects/association.py +19 -0
  483. merge/types/crm/custom_objects/association_list_params.py +57 -0
  484. merge/types/crm/engagement.py +64 -0
  485. merge/types/crm/engagement_create_params.py +61 -0
  486. merge/types/crm/engagement_list_params.py +60 -0
  487. merge/types/crm/engagement_list_remote_field_classes_params.py +30 -0
  488. merge/types/crm/engagement_response.py +30 -0
  489. merge/types/crm/engagement_retrieve_params.py +28 -0
  490. merge/types/crm/engagement_type.py +38 -0
  491. merge/types/crm/engagement_type_list_params.py +54 -0
  492. merge/types/crm/engagement_type_list_remote_field_classes_params.py +30 -0
  493. merge/types/crm/engagement_type_retrieve_params.py +21 -0
  494. merge/types/crm/engagement_update_params.py +61 -0
  495. merge/types/crm/engagements/__init__.py +3 -0
  496. merge/types/crm/issue_list_params.py +72 -0
  497. merge/types/crm/lead.py +111 -0
  498. merge/types/crm/lead_create_params.py +386 -0
  499. merge/types/crm/lead_list_params.py +69 -0
  500. merge/types/crm/lead_list_remote_field_classes_params.py +30 -0
  501. merge/types/crm/lead_response.py +30 -0
  502. merge/types/crm/lead_retrieve_params.py +28 -0
  503. merge/types/crm/leads/__init__.py +3 -0
  504. merge/types/crm/link_token_create_params.py +66 -0
  505. merge/types/crm/linked_account_list_params.py +89 -0
  506. merge/types/crm/note.py +54 -0
  507. merge/types/crm/note_create_params.py +43 -0
  508. merge/types/crm/note_list_params.py +72 -0
  509. merge/types/crm/note_list_remote_field_classes_params.py +30 -0
  510. merge/types/crm/note_response.py +29 -0
  511. merge/types/crm/note_retrieve_params.py +28 -0
  512. merge/types/crm/notes/__init__.py +3 -0
  513. merge/types/crm/opportunities/__init__.py +3 -0
  514. merge/types/crm/opportunity.py +68 -0
  515. merge/types/crm/opportunity_create_params.py +63 -0
  516. merge/types/crm/opportunity_list_params.py +85 -0
  517. merge/types/crm/opportunity_list_remote_field_classes_params.py +30 -0
  518. merge/types/crm/opportunity_response.py +30 -0
  519. merge/types/crm/opportunity_retrieve_params.py +34 -0
  520. merge/types/crm/opportunity_update_params.py +63 -0
  521. merge/types/crm/passthrough_request_send_params.py +76 -0
  522. merge/types/crm/remote_key_generate_params.py +11 -0
  523. merge/types/crm/remote_key_regenerate_params.py +11 -0
  524. merge/types/crm/selective_sync_list_configurations_response.py +11 -0
  525. merge/types/crm/selective_sync_list_metadata_params.py +17 -0
  526. merge/types/crm/selective_sync_replace_configurations_params.py +29 -0
  527. merge/types/crm/selective_sync_replace_configurations_response.py +11 -0
  528. merge/types/crm/stage.py +37 -0
  529. merge/types/crm/stage_list_params.py +54 -0
  530. merge/types/crm/stage_list_remote_field_classes_params.py +30 -0
  531. merge/types/crm/stage_retrieve_params.py +21 -0
  532. merge/types/crm/sync_status_list_params.py +15 -0
  533. merge/types/crm/sync_status_resync_response.py +9 -0
  534. merge/types/crm/task.py +59 -0
  535. merge/types/crm/task_create_params.py +55 -0
  536. merge/types/crm/task_create_response.py +29 -0
  537. merge/types/crm/task_list_params.py +60 -0
  538. merge/types/crm/task_list_remote_field_classes_params.py +30 -0
  539. merge/types/crm/task_retrieve_params.py +28 -0
  540. merge/types/crm/task_update_params.py +55 -0
  541. merge/types/crm/tasks/__init__.py +3 -0
  542. merge/types/crm/user.py +43 -0
  543. merge/types/crm/user_ignore_row_params.py +18 -0
  544. merge/types/crm/user_list_params.py +54 -0
  545. merge/types/crm/user_list_remote_field_classes_params.py +30 -0
  546. merge/types/crm/user_retrieve_params.py +21 -0
  547. merge/types/crm/webhook_receiver_create_params.py +15 -0
  548. merge/types/crm/webhook_receiver_list_response.py +9 -0
  549. merge/types/file_storage/__init__.py +65 -0
  550. merge/types/file_storage/common_model_scope_retrieve_params.py +12 -0
  551. merge/types/file_storage/common_model_scope_update_params.py +21 -0
  552. merge/types/file_storage/drive.py +31 -0
  553. merge/types/file_storage/drive_list_params.py +54 -0
  554. merge/types/file_storage/drive_retrieve_params.py +15 -0
  555. merge/types/file_storage/file.py +59 -0
  556. merge/types/file_storage/file_create_params.py +60 -0
  557. merge/types/file_storage/file_list_params.py +66 -0
  558. merge/types/file_storage/file_response.py +30 -0
  559. merge/types/file_storage/file_retrieve_params.py +22 -0
  560. merge/types/file_storage/files/__init__.py +3 -0
  561. merge/types/file_storage/folder.py +53 -0
  562. merge/types/file_storage/folder_create_params.py +55 -0
  563. merge/types/file_storage/folder_list_params.py +69 -0
  564. merge/types/file_storage/folder_response.py +31 -0
  565. merge/types/file_storage/folder_retrieve_params.py +22 -0
  566. merge/types/file_storage/folders/__init__.py +3 -0
  567. merge/types/file_storage/group.py +32 -0
  568. merge/types/file_storage/group_list_params.py +48 -0
  569. merge/types/file_storage/group_retrieve_params.py +15 -0
  570. merge/types/file_storage/issue_list_params.py +72 -0
  571. merge/types/file_storage/link_token_create_params.py +66 -0
  572. merge/types/file_storage/linked_account_list_params.py +89 -0
  573. merge/types/file_storage/passthrough_request_send_params.py +76 -0
  574. merge/types/file_storage/remote_key_generate_params.py +11 -0
  575. merge/types/file_storage/remote_key_regenerate_params.py +11 -0
  576. merge/types/file_storage/selective_sync_list_configurations_response.py +11 -0
  577. merge/types/file_storage/selective_sync_list_metadata_params.py +17 -0
  578. merge/types/file_storage/selective_sync_replace_configurations_params.py +29 -0
  579. merge/types/file_storage/selective_sync_replace_configurations_response.py +11 -0
  580. merge/types/file_storage/sync_status_list_params.py +15 -0
  581. merge/types/file_storage/sync_status_resync_response.py +9 -0
  582. merge/types/file_storage/user.py +31 -0
  583. merge/types/file_storage/user_list_params.py +48 -0
  584. merge/types/file_storage/user_retrieve_params.py +15 -0
  585. merge/types/file_storage/webhook_receiver_create_params.py +15 -0
  586. merge/types/file_storage/webhook_receiver_list_response.py +9 -0
  587. merge/types/hris/__init__.py +103 -0
  588. merge/types/hris/bank_info.py +48 -0
  589. merge/types/hris/bank_list_params.py +78 -0
  590. merge/types/hris/bank_retrieve_params.py +28 -0
  591. merge/types/hris/benefit.py +41 -0
  592. merge/types/hris/benefit_list_params.py +57 -0
  593. merge/types/hris/benefit_retrieve_params.py +22 -0
  594. merge/types/hris/common_model_scope_retrieve_params.py +12 -0
  595. merge/types/hris/common_model_scope_update_params.py +21 -0
  596. merge/types/hris/company.py +35 -0
  597. merge/types/hris/company_list_params.py +48 -0
  598. merge/types/hris/company_retrieve_params.py +15 -0
  599. merge/types/hris/created_employee_response.py +31 -0
  600. merge/types/hris/employee.py +167 -0
  601. merge/types/hris/employee_create_params.py +164 -0
  602. merge/types/hris/employee_ignore_params.py +18 -0
  603. merge/types/hris/employee_list_params.py +162 -0
  604. merge/types/hris/employee_payroll_run.py +149 -0
  605. merge/types/hris/employee_payroll_run_list_params.py +77 -0
  606. merge/types/hris/employee_payroll_run_retrieve_params.py +22 -0
  607. merge/types/hris/employee_retrieve_params.py +68 -0
  608. merge/types/hris/employees/__init__.py +3 -0
  609. merge/types/hris/employment.py +718 -0
  610. merge/types/hris/employment_list_params.py +98 -0
  611. merge/types/hris/employment_retrieve_params.py +60 -0
  612. merge/types/hris/group.py +42 -0
  613. merge/types/hris/group_list_params.py +60 -0
  614. merge/types/hris/group_retrieve_params.py +21 -0
  615. merge/types/hris/issue_list_params.py +72 -0
  616. merge/types/hris/link_token_create_params.py +66 -0
  617. merge/types/hris/linked_account_list_params.py +89 -0
  618. merge/types/hris/location.py +309 -0
  619. merge/types/hris/location_list_params.py +54 -0
  620. merge/types/hris/location_retrieve_params.py +21 -0
  621. merge/types/hris/passthrough_request_send_params.py +76 -0
  622. merge/types/hris/pay_group.py +29 -0
  623. merge/types/hris/pay_group_list_params.py +48 -0
  624. merge/types/hris/pay_group_retrieve_params.py +15 -0
  625. merge/types/hris/payroll_run.py +54 -0
  626. merge/types/hris/payroll_run_list_params.py +78 -0
  627. merge/types/hris/payroll_run_retrieve_params.py +21 -0
  628. merge/types/hris/remote_key_generate_params.py +11 -0
  629. merge/types/hris/remote_key_regenerate_params.py +11 -0
  630. merge/types/hris/selective_sync_list_configurations_response.py +11 -0
  631. merge/types/hris/selective_sync_list_metadata_params.py +17 -0
  632. merge/types/hris/selective_sync_replace_configurations_params.py +29 -0
  633. merge/types/hris/selective_sync_replace_configurations_response.py +11 -0
  634. merge/types/hris/sync_status_list_params.py +15 -0
  635. merge/types/hris/sync_status_resync_response.py +9 -0
  636. merge/types/hris/team_list_params.py +57 -0
  637. merge/types/hris/team_retrieve_params.py +22 -0
  638. merge/types/hris/time_off/__init__.py +5 -0
  639. merge/types/hris/time_off/time_off.py +69 -0
  640. merge/types/hris/time_off_balance.py +46 -0
  641. merge/types/hris/time_off_balance_list_params.py +77 -0
  642. merge/types/hris/time_off_balance_retrieve_params.py +28 -0
  643. merge/types/hris/time_off_create_params.py +75 -0
  644. merge/types/hris/time_off_list_params.py +108 -0
  645. merge/types/hris/time_off_response.py +30 -0
  646. merge/types/hris/time_off_retrieve_params.py +44 -0
  647. merge/types/hris/webhook_receiver_create_params.py +15 -0
  648. merge/types/hris/webhook_receiver_list_response.py +9 -0
  649. merge/types/marketing/__init__.py +113 -0
  650. merge/types/marketing/action.py +41 -0
  651. merge/types/marketing/action_create_params.py +44 -0
  652. merge/types/marketing/action_list_params.py +48 -0
  653. merge/types/marketing/action_response.py +30 -0
  654. merge/types/marketing/action_retrieve_params.py +15 -0
  655. merge/types/marketing/actions/__init__.py +3 -0
  656. merge/types/marketing/automation.py +53 -0
  657. merge/types/marketing/automation_create_params.py +60 -0
  658. merge/types/marketing/automation_list_params.py +48 -0
  659. merge/types/marketing/automation_list_recipients_params.py +24 -0
  660. merge/types/marketing/automation_response.py +31 -0
  661. merge/types/marketing/automation_retrieve_params.py +15 -0
  662. merge/types/marketing/automations/__init__.py +3 -0
  663. merge/types/marketing/campaign.py +38 -0
  664. merge/types/marketing/campaign_create_params.py +39 -0
  665. merge/types/marketing/campaign_list_contacts_params.py +24 -0
  666. merge/types/marketing/campaign_list_params.py +48 -0
  667. merge/types/marketing/campaign_response.py +31 -0
  668. merge/types/marketing/campaign_retrieve_params.py +15 -0
  669. merge/types/marketing/campaigns/__init__.py +3 -0
  670. merge/types/marketing/common_model_scope_retrieve_params.py +12 -0
  671. merge/types/marketing/common_model_scope_update_params.py +21 -0
  672. merge/types/marketing/contact_create_params.py +384 -0
  673. merge/types/marketing/contact_list.py +38 -0
  674. merge/types/marketing/contact_list_create_params.py +34 -0
  675. merge/types/marketing/contact_list_create_response.py +29 -0
  676. merge/types/marketing/contact_list_list_params.py +48 -0
  677. merge/types/marketing/contact_list_list_subscribers_params.py +24 -0
  678. merge/types/marketing/contact_list_params.py +48 -0
  679. merge/types/marketing/contact_list_retrieve_params.py +15 -0
  680. merge/types/marketing/contact_lists/__init__.py +3 -0
  681. merge/types/marketing/contact_response.py +28 -0
  682. merge/types/marketing/contact_retrieve_params.py +15 -0
  683. merge/types/marketing/contacts/__init__.py +3 -0
  684. merge/types/marketing/email.py +73 -0
  685. merge/types/marketing/email_list_params.py +48 -0
  686. merge/types/marketing/email_list_recipients_params.py +24 -0
  687. merge/types/marketing/email_retrieve_params.py +15 -0
  688. merge/types/marketing/event.py +47 -0
  689. merge/types/marketing/event_list_contacts_params.py +24 -0
  690. merge/types/marketing/event_list_params.py +48 -0
  691. merge/types/marketing/event_retrieve_params.py +15 -0
  692. merge/types/marketing/issue_list_params.py +72 -0
  693. merge/types/marketing/link_token_create_params.py +66 -0
  694. merge/types/marketing/linked_account_list_params.py +89 -0
  695. merge/types/marketing/message.py +35 -0
  696. merge/types/marketing/message_list_params.py +48 -0
  697. merge/types/marketing/message_list_recipients_params.py +24 -0
  698. merge/types/marketing/message_retrieve_params.py +15 -0
  699. merge/types/marketing/passthrough_request_send_params.py +76 -0
  700. merge/types/marketing/remote_key_generate_params.py +11 -0
  701. merge/types/marketing/remote_key_regenerate_params.py +11 -0
  702. merge/types/marketing/selective_sync_list_configurations_response.py +11 -0
  703. merge/types/marketing/selective_sync_list_metadata_params.py +17 -0
  704. merge/types/marketing/selective_sync_replace_configurations_params.py +29 -0
  705. merge/types/marketing/selective_sync_replace_configurations_response.py +11 -0
  706. merge/types/marketing/sync_status_list_params.py +15 -0
  707. merge/types/marketing/sync_status_resync_response.py +9 -0
  708. merge/types/marketing/template.py +48 -0
  709. merge/types/marketing/template_create_params.py +45 -0
  710. merge/types/marketing/template_list_params.py +48 -0
  711. merge/types/marketing/template_response.py +31 -0
  712. merge/types/marketing/template_retrieve_params.py +15 -0
  713. merge/types/marketing/templates/__init__.py +3 -0
  714. merge/types/marketing/user.py +47 -0
  715. merge/types/marketing/user_list_params.py +48 -0
  716. merge/types/marketing/user_retrieve_params.py +15 -0
  717. merge/types/marketing/webhook_receiver_create_params.py +15 -0
  718. merge/types/marketing/webhook_receiver_list_response.py +9 -0
  719. merge/types/shared/__init__.py +33 -0
  720. merge/types/shared/account.py +745 -0
  721. merge/types/shared/account_detail.py +45 -0
  722. merge/types/shared/account_details_and_actions.py +78 -0
  723. merge/types/shared/account_token.py +56 -0
  724. merge/types/shared/address.py +303 -0
  725. merge/types/shared/attachment.py +60 -0
  726. merge/types/shared/available_action.py +68 -0
  727. merge/types/shared/common_model_scope.py +56 -0
  728. merge/types/shared/condition_schema.py +56 -0
  729. merge/types/shared/contact.py +397 -0
  730. merge/types/shared/country.py +257 -0
  731. merge/types/shared/debug_log.py +22 -0
  732. merge/types/shared/issue.py +31 -0
  733. merge/types/shared/link_token.py +15 -0
  734. merge/types/shared/linked_account_selective_sync_configuration.py +35 -0
  735. merge/types/shared/meta_response.py +25 -0
  736. merge/types/shared/remote_data.py +13 -0
  737. merge/types/shared/remote_field_class.py +54 -0
  738. merge/types/shared/remote_key.py +12 -0
  739. merge/types/shared/remote_response.py +28 -0
  740. merge/types/shared/remote_user.py +51 -0
  741. merge/types/shared/sync_status.py +36 -0
  742. merge/types/shared/tag.py +27 -0
  743. merge/types/shared/team.py +35 -0
  744. merge/types/shared/validation_error.py +21 -0
  745. merge/types/shared/validation_warning.py +21 -0
  746. merge/types/shared/webhook_receiver.py +15 -0
  747. merge/types/shared_params/__init__.py +33 -0
  748. merge/types/shared_params/account.py +700 -0
  749. merge/types/shared_params/account_detail.py +20 -0
  750. merge/types/shared_params/account_details_and_actions.py +78 -0
  751. merge/types/shared_params/account_token.py +54 -0
  752. merge/types/shared_params/address.py +295 -0
  753. merge/types/shared_params/attachment.py +50 -0
  754. merge/types/shared_params/available_action.py +66 -0
  755. merge/types/shared_params/common_model_scope.py +56 -0
  756. merge/types/shared_params/condition_schema.py +49 -0
  757. merge/types/shared_params/contact.py +374 -0
  758. merge/types/shared_params/country.py +259 -0
  759. merge/types/shared_params/debug_log.py +23 -0
  760. merge/types/shared_params/issue.py +25 -0
  761. merge/types/shared_params/link_token.py +15 -0
  762. merge/types/shared_params/linked_account_selective_sync_configuration.py +11 -0
  763. merge/types/shared_params/meta_response.py +25 -0
  764. merge/types/shared_params/remote_data.py +13 -0
  765. merge/types/shared_params/remote_field_class.py +54 -0
  766. merge/types/shared_params/remote_key.py +13 -0
  767. merge/types/shared_params/remote_response.py +27 -0
  768. merge/types/shared_params/remote_user.py +40 -0
  769. merge/types/shared_params/sync_status.py +38 -0
  770. merge/types/shared_params/tag.py +19 -0
  771. merge/types/shared_params/team.py +22 -0
  772. merge/types/shared_params/validation_error.py +21 -0
  773. merge/types/shared_params/validation_warning.py +21 -0
  774. merge/types/shared_params/webhook_receiver.py +15 -0
  775. merge/types/ticketing/__init__.py +94 -0
  776. merge/types/ticketing/account_list_params.py +48 -0
  777. merge/types/ticketing/account_retrieve_params.py +15 -0
  778. merge/types/ticketing/attachment_create_params.py +59 -0
  779. merge/types/ticketing/attachment_create_response.py +28 -0
  780. merge/types/ticketing/attachment_list_params.py +57 -0
  781. merge/types/ticketing/attachment_retrieve_params.py +22 -0
  782. merge/types/ticketing/attachments/__init__.py +3 -0
  783. merge/types/ticketing/collection.py +42 -0
  784. merge/types/ticketing/collection_list_params.py +73 -0
  785. merge/types/ticketing/collection_list_users_params.py +31 -0
  786. merge/types/ticketing/collection_retrieve_params.py +28 -0
  787. merge/types/ticketing/comment.py +46 -0
  788. merge/types/ticketing/comment_create_params.py +46 -0
  789. merge/types/ticketing/comment_list_params.py +57 -0
  790. merge/types/ticketing/comment_response.py +29 -0
  791. merge/types/ticketing/comment_retrieve_params.py +22 -0
  792. merge/types/ticketing/comments/__init__.py +3 -0
  793. merge/types/ticketing/common_model_scope_retrieve_params.py +12 -0
  794. merge/types/ticketing/common_model_scope_update_params.py +21 -0
  795. merge/types/ticketing/contact_list_params.py +54 -0
  796. merge/types/ticketing/contact_retrieve_params.py +22 -0
  797. merge/types/ticketing/issue_list_params.py +72 -0
  798. merge/types/ticketing/link_token_create_params.py +66 -0
  799. merge/types/ticketing/linked_account_list_params.py +89 -0
  800. merge/types/ticketing/passthrough_request_send_params.py +76 -0
  801. merge/types/ticketing/project.py +32 -0
  802. merge/types/ticketing/project_list_params.py +48 -0
  803. merge/types/ticketing/project_list_users_params.py +31 -0
  804. merge/types/ticketing/project_retrieve_params.py +15 -0
  805. merge/types/ticketing/remote_key_generate_params.py +11 -0
  806. merge/types/ticketing/remote_key_regenerate_params.py +11 -0
  807. merge/types/ticketing/selective_sync_list_configurations_response.py +11 -0
  808. merge/types/ticketing/selective_sync_list_metadata_params.py +17 -0
  809. merge/types/ticketing/selective_sync_replace_configurations_params.py +29 -0
  810. merge/types/ticketing/selective_sync_replace_configurations_response.py +11 -0
  811. merge/types/ticketing/sync_status_list_params.py +15 -0
  812. merge/types/ticketing/sync_status_resync_response.py +9 -0
  813. merge/types/ticketing/tag_list_params.py +48 -0
  814. merge/types/ticketing/tag_retrieve_params.py +15 -0
  815. merge/types/ticketing/team_list_params.py +48 -0
  816. merge/types/ticketing/team_retrieve_params.py +15 -0
  817. merge/types/ticketing/ticket.py +100 -0
  818. merge/types/ticketing/ticket_create_params.py +91 -0
  819. merge/types/ticketing/ticket_list_collaborators_params.py +31 -0
  820. merge/types/ticketing/ticket_list_params.py +171 -0
  821. merge/types/ticketing/ticket_list_remote_field_classes_params.py +24 -0
  822. merge/types/ticketing/ticket_response.py +29 -0
  823. merge/types/ticketing/ticket_retrieve_params.py +52 -0
  824. merge/types/ticketing/ticket_update_params.py +89 -0
  825. merge/types/ticketing/tickets/__init__.py +3 -0
  826. merge/types/ticketing/user.py +40 -0
  827. merge/types/ticketing/user_list_params.py +60 -0
  828. merge/types/ticketing/user_retrieve_params.py +22 -0
  829. merge/types/ticketing/webhook_receiver_create_params.py +15 -0
  830. merge/types/ticketing/webhook_receiver_list_response.py +9 -0
  831. mergepythonclient-0.0.1.dist-info/LICENSE.md +16 -0
  832. mergepythonclient-0.0.1.dist-info/METADATA +281 -0
  833. mergepythonclient-0.0.1.dist-info/RECORD +834 -0
  834. mergepythonclient-0.0.1.dist-info/WHEEL +4 -0
merge/_base_client.py ADDED
@@ -0,0 +1,1431 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import time
5
+ import uuid
6
+ import inspect
7
+ import platform
8
+ from random import random
9
+ from typing import (
10
+ Any,
11
+ Dict,
12
+ List,
13
+ Type,
14
+ Union,
15
+ Generic,
16
+ Mapping,
17
+ TypeVar,
18
+ Iterable,
19
+ Iterator,
20
+ Optional,
21
+ Generator,
22
+ AsyncIterator,
23
+ cast,
24
+ overload,
25
+ )
26
+ from functools import lru_cache
27
+ from typing_extensions import Literal, get_origin
28
+
29
+ import anyio
30
+ import httpx
31
+ import distro
32
+ import pydantic
33
+ from httpx import URL, Limits
34
+ from pydantic import PrivateAttr
35
+
36
+ from . import _base_exceptions as exceptions
37
+ from ._qs import Querystring
38
+ from ._types import (
39
+ NOT_GIVEN,
40
+ Body,
41
+ Omit,
42
+ Query,
43
+ ModelT,
44
+ Headers,
45
+ Timeout,
46
+ NoneType,
47
+ NotGiven,
48
+ Transport,
49
+ AnyMapping,
50
+ ProxiesTypes,
51
+ RequestFiles,
52
+ RequestOptions,
53
+ UnknownResponse,
54
+ ModelBuilderProtocol,
55
+ )
56
+ from ._utils import is_dict, is_mapping
57
+ from ._models import (
58
+ BaseModel,
59
+ GenericModel,
60
+ FinalRequestOptions,
61
+ validate_type,
62
+ construct_type,
63
+ )
64
+ from ._base_exceptions import (
65
+ APIStatusError,
66
+ APITimeoutError,
67
+ APIConnectionError,
68
+ APIResponseValidationError,
69
+ )
70
+
71
+ # TODO: make base page type vars covariant
72
+ SyncPageT = TypeVar("SyncPageT", bound="BaseSyncPage[Any]")
73
+ AsyncPageT = TypeVar("AsyncPageT", bound="BaseAsyncPage[Any]")
74
+
75
+
76
+ ResponseT = TypeVar(
77
+ "ResponseT",
78
+ bound=Union[
79
+ str,
80
+ None,
81
+ BaseModel,
82
+ List[Any],
83
+ Dict[str, Any],
84
+ httpx.Response,
85
+ UnknownResponse,
86
+ ModelBuilderProtocol,
87
+ ],
88
+ )
89
+
90
+ _T = TypeVar("_T")
91
+ _T_co = TypeVar("_T_co", covariant=True)
92
+
93
+ DEFAULT_TIMEOUT = Timeout(timeout=60.0, connect=5.0)
94
+ DEFAULT_MAX_RETRIES = 2
95
+ DEFAULT_LIMITS = Limits(max_connections=100, max_keepalive_connections=20)
96
+
97
+
98
+ class StopStreaming(Exception):
99
+ """Raised internally when processing of a streamed response should be stopped."""
100
+
101
+
102
+ class Stream(Generic[ResponseT]):
103
+ response: httpx.Response
104
+
105
+ def __init__(
106
+ self,
107
+ *,
108
+ cast_to: type[ResponseT],
109
+ response: httpx.Response,
110
+ client: SyncAPIClient,
111
+ ) -> None:
112
+ self.response = response
113
+ self._cast_to = cast_to
114
+ self._client = client
115
+ self._iterator = self.__iter()
116
+
117
+ def __next__(self) -> ResponseT:
118
+ return self._iterator.__next__()
119
+
120
+ def __iter__(self) -> Iterator[ResponseT]:
121
+ for item in self._iterator:
122
+ yield item
123
+
124
+ def __iter(self) -> Iterator[ResponseT]:
125
+ cast_to = self._cast_to
126
+ response = self.response
127
+ process_line = self._client._process_stream_line
128
+ process_data = self._client._process_response_data
129
+
130
+ awaiting_ping_data = False
131
+ for raw_line in response.iter_lines():
132
+ if not raw_line or raw_line == "\n":
133
+ continue
134
+
135
+ if raw_line.startswith("event: ping"):
136
+ awaiting_ping_data = True
137
+ continue
138
+ if awaiting_ping_data:
139
+ awaiting_ping_data = False
140
+ continue
141
+
142
+ try:
143
+ line = process_line(raw_line)
144
+ except StopStreaming:
145
+ # we are done!
146
+ break
147
+
148
+ yield process_data(data=json.loads(line), cast_to=cast_to, response=response)
149
+
150
+
151
+ class AsyncStream(Generic[ResponseT]):
152
+ response: httpx.Response
153
+
154
+ def __init__(
155
+ self,
156
+ *,
157
+ cast_to: type[ResponseT],
158
+ response: httpx.Response,
159
+ client: AsyncAPIClient,
160
+ ) -> None:
161
+ self.response = response
162
+ self._cast_to = cast_to
163
+ self._client = client
164
+ self._iterator = self.__iter()
165
+
166
+ async def __anext__(self) -> ResponseT:
167
+ return await self._iterator.__anext__()
168
+
169
+ async def __aiter__(self) -> AsyncIterator[ResponseT]:
170
+ async for item in self._iterator:
171
+ yield item
172
+
173
+ async def __iter(self) -> AsyncIterator[ResponseT]:
174
+ cast_to = self._cast_to
175
+ response = self.response
176
+ process_line = self._client._process_stream_line
177
+ process_data = self._client._process_response_data
178
+
179
+ awaiting_ping_data = False
180
+ async for raw_line in response.aiter_lines():
181
+ if not raw_line or raw_line == "\n":
182
+ continue
183
+
184
+ if raw_line.startswith("event: ping"):
185
+ awaiting_ping_data = True
186
+ continue
187
+ if awaiting_ping_data:
188
+ awaiting_ping_data = False
189
+ continue
190
+
191
+ try:
192
+ line = process_line(raw_line)
193
+ except StopStreaming:
194
+ # we are done!
195
+ break
196
+
197
+ yield process_data(data=json.loads(line), cast_to=cast_to, response=response)
198
+
199
+
200
+ class PageInfo:
201
+ """Stores the necesary information to build the request to retrieve the next page.
202
+
203
+ Either `url` or `params` must be set.
204
+ """
205
+
206
+ url: URL | NotGiven
207
+ params: Query | NotGiven
208
+
209
+ @overload
210
+ def __init__(
211
+ self,
212
+ *,
213
+ url: URL,
214
+ ) -> None:
215
+ ...
216
+
217
+ @overload
218
+ def __init__(
219
+ self,
220
+ *,
221
+ params: Query,
222
+ ) -> None:
223
+ ...
224
+
225
+ def __init__(
226
+ self,
227
+ *,
228
+ url: URL | NotGiven = NOT_GIVEN,
229
+ params: Query | NotGiven = NOT_GIVEN,
230
+ ) -> None:
231
+ self.url = url
232
+ self.params = params
233
+
234
+
235
+ class BasePage(GenericModel, Generic[ModelT]):
236
+ _options: FinalRequestOptions = PrivateAttr()
237
+ _model: Type[ModelT] = PrivateAttr()
238
+
239
+ def has_next_page(self) -> bool:
240
+ items = self._get_page_items()
241
+ if not items:
242
+ return False
243
+ return self.next_page_info() is not None
244
+
245
+ def next_page_info(self) -> Optional[PageInfo]:
246
+ ...
247
+
248
+ def _get_page_items(self) -> Iterable[ModelT]: # type: ignore[empty-body]
249
+ ...
250
+
251
+ def _params_from_url(self, url: URL) -> httpx.QueryParams:
252
+ # TODO: do we have to preprocess params here?
253
+ return httpx.QueryParams(cast(Any, self._options.params)).merge(url.params)
254
+
255
+ def _info_to_options(self, info: PageInfo) -> FinalRequestOptions:
256
+ options = self._options.copy()
257
+
258
+ if not isinstance(info.params, NotGiven):
259
+ options.params = {**options.params, **info.params}
260
+ return options
261
+
262
+ if not isinstance(info.url, NotGiven):
263
+ params = self._params_from_url(info.url)
264
+ url = info.url.copy_with(params=params)
265
+ options.params = dict(url.params)
266
+ options.url = str(url)
267
+ return options
268
+
269
+ raise ValueError("Unexpected PageInfo state")
270
+
271
+
272
+ class BaseSyncPage(BasePage[ModelT], Generic[ModelT]):
273
+ _client: SyncAPIClient = pydantic.PrivateAttr()
274
+
275
+ def _set_private_attributes(
276
+ self,
277
+ client: SyncAPIClient,
278
+ model: Type[ModelT],
279
+ options: FinalRequestOptions,
280
+ ) -> None:
281
+ self._model = model
282
+ self._client = client
283
+ self._options = options
284
+
285
+ # Pydantic uses a custom `__iter__` method to support casting BaseModels
286
+ # to dictionaries. e.g. dict(model).
287
+ # As we want to support `for item in page`, this is inherently incompatible
288
+ # with the default pydantic behaviour. It is not possible to support both
289
+ # use cases at once. Fortunately, this is not a big deal as all other pydantic
290
+ # methods should continue to work as expected as there is an alternative method
291
+ # to cast a model to a dictionary, model.dict(), which is used internally
292
+ # by pydantic.
293
+ def __iter__(self) -> Iterator[ModelT]: # type: ignore
294
+ for page in self.iter_pages():
295
+ for item in page._get_page_items():
296
+ yield item
297
+
298
+ def iter_pages(self: SyncPageT) -> Iterator[SyncPageT]:
299
+ page = self
300
+ while True:
301
+ yield page
302
+ if page.has_next_page():
303
+ page = page.get_next_page()
304
+ else:
305
+ return
306
+
307
+ def get_next_page(self: SyncPageT) -> SyncPageT:
308
+ info = self.next_page_info()
309
+ if not info:
310
+ raise RuntimeError(
311
+ "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`."
312
+ )
313
+
314
+ options = self._info_to_options(info)
315
+ return self._client._request_api_list(self._model, page=self.__class__, options=options)
316
+
317
+
318
+ class AsyncPaginator(Generic[ModelT, AsyncPageT]):
319
+ def __init__(
320
+ self,
321
+ client: AsyncAPIClient,
322
+ options: FinalRequestOptions,
323
+ page_cls: Type[AsyncPageT],
324
+ model: Type[ModelT],
325
+ ) -> None:
326
+ self._model = model
327
+ self._client = client
328
+ self._options = options
329
+ self._page_cls = page_cls
330
+
331
+ def __await__(self) -> Generator[Any, None, AsyncPageT]:
332
+ return self._get_page().__await__()
333
+
334
+ async def _get_page(self) -> AsyncPageT:
335
+ page = await self._client.request(self._page_cls, self._options)
336
+ page._set_private_attributes( # pyright: ignore[reportPrivateUsage]
337
+ model=self._model,
338
+ options=self._options,
339
+ client=self._client,
340
+ )
341
+ return page
342
+
343
+ async def __aiter__(self) -> AsyncIterator[ModelT]:
344
+ # https://github.com/microsoft/pyright/issues/3464
345
+ page = cast(
346
+ AsyncPageT,
347
+ await self, # type: ignore
348
+ )
349
+ async for item in page:
350
+ yield item
351
+
352
+
353
+ class BaseAsyncPage(BasePage[ModelT], Generic[ModelT]):
354
+ _client: AsyncAPIClient = pydantic.PrivateAttr()
355
+
356
+ def _set_private_attributes(
357
+ self,
358
+ model: Type[ModelT],
359
+ client: AsyncAPIClient,
360
+ options: FinalRequestOptions,
361
+ ) -> None:
362
+ self._model = model
363
+ self._client = client
364
+ self._options = options
365
+
366
+ async def __aiter__(self) -> AsyncIterator[ModelT]:
367
+ async for page in self.iter_pages():
368
+ for item in page._get_page_items():
369
+ yield item
370
+
371
+ async def iter_pages(self: AsyncPageT) -> AsyncIterator[AsyncPageT]:
372
+ page = self
373
+ while True:
374
+ yield page
375
+ if page.has_next_page():
376
+ page = await page.get_next_page()
377
+ else:
378
+ return
379
+
380
+ async def get_next_page(self: AsyncPageT) -> AsyncPageT:
381
+ info = self.next_page_info()
382
+ if not info:
383
+ raise RuntimeError(
384
+ "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`."
385
+ )
386
+
387
+ options = self._info_to_options(info)
388
+ return await self._client._request_api_list(self._model, page=self.__class__, options=options)
389
+
390
+
391
+ class BaseClient:
392
+ _client: httpx.Client | httpx.AsyncClient
393
+ _version: str
394
+ max_retries: int
395
+ timeout: Union[float, Timeout, None]
396
+ _limits: httpx.Limits
397
+ _strict_response_validation: bool
398
+ _idempotency_header: str | None
399
+
400
+ def __init__(
401
+ self,
402
+ *,
403
+ version: str,
404
+ _strict_response_validation: bool,
405
+ max_retries: int = DEFAULT_MAX_RETRIES,
406
+ timeout: float | Timeout | None = DEFAULT_TIMEOUT,
407
+ limits: httpx.Limits,
408
+ custom_headers: Mapping[str, str] | None = None,
409
+ custom_query: Mapping[str, object] | None = None,
410
+ ) -> None:
411
+ self._version = version
412
+ self.max_retries = max_retries
413
+ self.timeout = timeout
414
+ self._limits = limits
415
+ self._custom_headers = custom_headers or {}
416
+ self._custom_query = custom_query or {}
417
+ self._strict_response_validation = _strict_response_validation
418
+ self._idempotency_header = None
419
+
420
+ def _make_status_error_from_response(
421
+ self,
422
+ request: httpx.Request,
423
+ response: httpx.Response,
424
+ ) -> APIStatusError:
425
+ err_text = response.text.strip()
426
+ body = err_text
427
+
428
+ try:
429
+ body = json.loads(err_text)
430
+ err_msg = f"Error code: {response.status_code} - {body}"
431
+ except Exception:
432
+ err_msg = err_text or f"Error code: {response.status_code}"
433
+
434
+ return self._make_status_error(err_msg, body=body, request=request, response=response)
435
+
436
+ def _make_status_error(
437
+ self,
438
+ err_msg: str,
439
+ *,
440
+ body: object,
441
+ request: httpx.Request,
442
+ response: httpx.Response,
443
+ ) -> APIStatusError:
444
+ if response.status_code == 400:
445
+ return exceptions.BadRequestError(err_msg, request=request, response=response, body=body)
446
+ if response.status_code == 401:
447
+ return exceptions.AuthenticationError(err_msg, request=request, response=response, body=body)
448
+ if response.status_code == 403:
449
+ return exceptions.PermissionDeniedError(err_msg, request=request, response=response, body=body)
450
+ if response.status_code == 404:
451
+ return exceptions.NotFoundError(err_msg, request=request, response=response, body=body)
452
+ if response.status_code == 409:
453
+ return exceptions.ConflictError(err_msg, request=request, response=response, body=body)
454
+ if response.status_code == 422:
455
+ return exceptions.UnprocessableEntityError(err_msg, request=request, response=response, body=body)
456
+ if response.status_code == 429:
457
+ return exceptions.RateLimitError(err_msg, request=request, response=response, body=body)
458
+ if response.status_code >= 500:
459
+ return exceptions.InternalServerError(err_msg, request=request, response=response, body=body)
460
+ return APIStatusError(err_msg, request=request, response=response, body=body)
461
+
462
+ def _remaining_retries(
463
+ self,
464
+ remaining_retries: Optional[int],
465
+ options: FinalRequestOptions,
466
+ ) -> int:
467
+ return remaining_retries if remaining_retries is not None else options.get_max_retries(self.max_retries)
468
+
469
+ def _build_headers(self, options: FinalRequestOptions) -> httpx.Headers:
470
+ custom_headers = options.headers or {}
471
+ headers_dict = _merge_mappings(self.default_headers, custom_headers)
472
+ self._validate_headers(headers_dict, custom_headers)
473
+
474
+ headers = httpx.Headers(headers_dict)
475
+
476
+ idempotency_header = self._idempotency_header
477
+ if idempotency_header and options.method.lower() != "get" and idempotency_header not in headers:
478
+ if not options.idempotency_key:
479
+ options.idempotency_key = self._idempotency_key()
480
+
481
+ headers[idempotency_header] = options.idempotency_key
482
+
483
+ return headers
484
+
485
+ def _build_request(
486
+ self,
487
+ options: FinalRequestOptions,
488
+ ) -> httpx.Request:
489
+ headers = self._build_headers(options)
490
+
491
+ kwargs: dict[str, Any] = {}
492
+
493
+ json_data = options.json_data
494
+ if options.extra_json is not None:
495
+ if json_data is None:
496
+ json_data = cast(Body, options.extra_json)
497
+ elif is_mapping(json_data):
498
+ json_data = _merge_mappings(json_data, options.extra_json)
499
+ else:
500
+ raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`")
501
+
502
+ params = _merge_mappings(self._custom_query, options.params)
503
+
504
+ # If the given Content-Type header is multipart/form-data then it
505
+ # has to be removed so that httpx can generate the header with
506
+ # additional information for us as it has to be in this form
507
+ # for the server to be able to correctly parse the request:
508
+ # multipart/form-data; boundary=---abc--
509
+ if headers.get("Content-Type") == "multipart/form-data":
510
+ headers.pop("Content-Type")
511
+
512
+ # As we are now sending multipart/form-data instead of application/json
513
+ # we need to tell httpx to use it, https://www.python-httpx.org/advanced/#multipart-file-encoding
514
+ if json_data:
515
+ if not is_dict(json_data):
516
+ raise TypeError(
517
+ f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead."
518
+ )
519
+ kwargs["data"] = self._serialize_multipartform(json_data)
520
+
521
+ # TODO: report this error to httpx
522
+ return self._client.build_request( # pyright: ignore[reportUnknownMemberType]
523
+ headers=headers,
524
+ timeout=self.timeout if isinstance(options.timeout, NotGiven) else options.timeout,
525
+ method=options.method,
526
+ url=options.url,
527
+ # the `Query` type that we use is incompatible with qs'
528
+ # `Params` type as it needs to be typed as `Mapping[str, object]`
529
+ # so that passing a `TypedDict` doesn't cause an error.
530
+ # https://github.com/microsoft/pyright/issues/3526#event-6715453066
531
+ params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None,
532
+ json=json_data,
533
+ files=options.files,
534
+ **kwargs,
535
+ )
536
+
537
+ def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, object]:
538
+ items = self.qs.stringify_items(
539
+ # TODO: type ignore is required as stringify_items is well typed but we can't be
540
+ # well typed without heavy validation.
541
+ data, # type: ignore
542
+ array_format="brackets",
543
+ )
544
+ serialized: dict[str, object] = {}
545
+ for key, value in items:
546
+ if key in serialized:
547
+ raise ValueError(f"Duplicate key encountered: {key}; This behaviour is not supported")
548
+ serialized[key] = value
549
+ return serialized
550
+
551
+ def _process_response(
552
+ self,
553
+ *,
554
+ cast_to: Type[ResponseT],
555
+ options: FinalRequestOptions,
556
+ response: httpx.Response,
557
+ ) -> ResponseT:
558
+ if cast_to is NoneType:
559
+ return cast(ResponseT, None)
560
+
561
+ if cast_to == str:
562
+ return cast(ResponseT, response.text)
563
+
564
+ origin = get_origin(cast_to) or cast_to
565
+
566
+ if inspect.isclass(origin) and issubclass(origin, httpx.Response):
567
+ # Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response
568
+ # and pass that class to our request functions. We cannot change the variance to be either
569
+ # covariant or contravariant as that makes our usage of ResponseT illegal. We could construct
570
+ # the response class ourselves but that is something that should be supported directly in httpx
571
+ # as it would be easy to incorrectly construct the Response object due to the multitude of arguments.
572
+ if cast_to != httpx.Response:
573
+ raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`")
574
+ return cast(ResponseT, response)
575
+
576
+ # The check here is necessary as we are subverting the the type system
577
+ # with casts as the relationship between TypeVars and Types are very strict
578
+ # which means we must return *exactly* what was input or transform it in a
579
+ # way that retains the TypeVar state. As we cannot do that in this function
580
+ # then we have to resort to using `cast`. At the time of writing, we know this
581
+ # to be safe as we have handled all the types that could be bound to the
582
+ # `ResponseT` TypeVar, however if that TypeVar is ever updated in the future, then
583
+ # this function would become unsafe but a type checker would not report an error.
584
+ if (
585
+ cast_to is not UnknownResponse
586
+ and not origin is list
587
+ and not origin is dict
588
+ and not origin is Union
589
+ and not issubclass(origin, BaseModel)
590
+ ):
591
+ raise RuntimeError(
592
+ f"Invalid state, expected {cast_to} to be a subclass type of {BaseModel}, {dict}, {list} or {Union}."
593
+ )
594
+
595
+ # split is required to handle cases where additional information is included
596
+ # in the response, e.g. application/json; charset=utf-8
597
+ content_type, *_ = response.headers.get("content-type").split(";")
598
+ if content_type != "application/json":
599
+ raise ValueError(
600
+ f"Expected Content-Type response header to be `application/json` but received {content_type} instead."
601
+ )
602
+
603
+ data = response.json()
604
+ return self._process_response_data(data=data, cast_to=cast_to, response=response)
605
+
606
+ def _process_response_data(
607
+ self,
608
+ *,
609
+ data: object,
610
+ cast_to: type[ResponseT],
611
+ response: httpx.Response,
612
+ ) -> ResponseT:
613
+ if data is None:
614
+ return cast(ResponseT, None)
615
+
616
+ if cast_to is UnknownResponse:
617
+ return cast(ResponseT, data)
618
+
619
+ if inspect.isclass(cast_to) and issubclass(cast_to, ModelBuilderProtocol):
620
+ return cast(ResponseT, cast_to.build(response=response, data=data))
621
+
622
+ if self._strict_response_validation:
623
+ return cast(ResponseT, validate_type(type_=cast_to, value=data))
624
+
625
+ return cast(ResponseT, construct_type(type_=cast_to, value=data))
626
+
627
+ def _process_stream_line(self, contents: str) -> str:
628
+ """Pre-process an indiviudal line from a streaming response"""
629
+ if contents == "data: [DONE]\n":
630
+ raise StopStreaming()
631
+
632
+ if contents.startswith("data: "):
633
+ return contents[6:]
634
+
635
+ return contents
636
+
637
+ @property
638
+ def qs(self) -> Querystring:
639
+ return Querystring()
640
+
641
+ @property
642
+ def custom_auth(self) -> httpx.Auth | None:
643
+ return None
644
+
645
+ @property
646
+ def auth_headers(self) -> dict[str, str]:
647
+ return {}
648
+
649
+ @property
650
+ def default_headers(self) -> dict[str, str | Omit]:
651
+ return {
652
+ "Content-Type": "application/json",
653
+ "User-Agent": self.user_agent,
654
+ **self.platform_headers(),
655
+ **self.auth_headers,
656
+ **self._custom_headers,
657
+ }
658
+
659
+ def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
660
+ """Validate the given default headers and custom headers.
661
+
662
+ Does nothing by default.
663
+ """
664
+ return
665
+
666
+ @property
667
+ def user_agent(self) -> str:
668
+ return f"{self.__class__.__name__}/Python {self._version}"
669
+
670
+ @property
671
+ def base_url(self) -> URL:
672
+ return self._client.base_url
673
+
674
+ @lru_cache(maxsize=None)
675
+ def platform_headers(self) -> Dict[str, str]:
676
+ return {
677
+ "X-Stainless-Lang": "python",
678
+ "X-Stainless-Package-Version": self._version,
679
+ "X-Stainless-OS": str(get_platform()),
680
+ "X-Stainless-Arch": str(get_architecture()),
681
+ "X-Stainless-Runtime": platform.python_implementation(),
682
+ "X-Stainless-Runtime-Version": platform.python_version(),
683
+ }
684
+
685
+ def _calculate_retry_timeout(
686
+ self,
687
+ remaining_retries: int,
688
+ options: FinalRequestOptions,
689
+ response_headers: Optional[httpx.Headers] = None,
690
+ ) -> float:
691
+ max_retries = options.get_max_retries(self.max_retries)
692
+ try:
693
+ # About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
694
+ #
695
+ # TODO: we may want to handle the case where the header is using the http-date syntax: "Retry-After:
696
+ # <http-date>". See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After#syntax for
697
+ # details.
698
+ retry_after = -1 if response_headers is None else int(response_headers.get("retry-after"))
699
+ except Exception:
700
+ retry_after = -1
701
+
702
+ # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says.
703
+ if 0 < retry_after <= 60:
704
+ return retry_after
705
+
706
+ initial_retry_delay = 0.5
707
+ max_retry_delay = 2.0
708
+ nb_retries = max_retries - remaining_retries
709
+
710
+ # Apply exponential backoff, but not more than the max.
711
+ sleep_seconds = min(initial_retry_delay * pow(nb_retries - 1, 2), max_retry_delay)
712
+
713
+ # Apply some jitter, plus-or-minus half a second.
714
+ jitter = random() - 0.5
715
+ timeout = sleep_seconds + jitter
716
+ return timeout if timeout >= 0 else 0
717
+
718
+ def _should_retry(self, response: httpx.Response) -> bool:
719
+ # Note: this is not a standard header
720
+ should_retry_header = response.headers.get("x-should-retry")
721
+
722
+ # If the server explicitly says whether or not to retry, obey.
723
+ if should_retry_header == "true":
724
+ return True
725
+ if should_retry_header == "false":
726
+ return False
727
+
728
+ # Retry on lock timeouts.
729
+ if response.status_code == 409:
730
+ return True
731
+
732
+ # Retry on rate limits.
733
+ if response.status_code == 429:
734
+ return True
735
+
736
+ # Retry internal errors.
737
+ if response.status_code >= 500:
738
+ return True
739
+
740
+ return False
741
+
742
+ def _idempotency_key(self) -> str:
743
+ return f"stainless-python-retry-{uuid.uuid4()}"
744
+
745
+
746
+ class SyncAPIClient(BaseClient):
747
+ _client: httpx.Client
748
+
749
+ def __init__(
750
+ self,
751
+ *,
752
+ version: str,
753
+ base_url: str,
754
+ max_retries: int = DEFAULT_MAX_RETRIES,
755
+ timeout: float | Timeout | None = DEFAULT_TIMEOUT,
756
+ transport: Transport | None = None,
757
+ proxies: ProxiesTypes | None = None,
758
+ limits: Limits | None = DEFAULT_LIMITS,
759
+ custom_headers: Mapping[str, str] | None = None,
760
+ custom_query: Mapping[str, object] | None = None,
761
+ _strict_response_validation: bool,
762
+ ) -> None:
763
+ limits = limits or DEFAULT_LIMITS
764
+ super().__init__(
765
+ version=version,
766
+ limits=limits,
767
+ timeout=timeout,
768
+ max_retries=max_retries,
769
+ custom_query=custom_query,
770
+ custom_headers=custom_headers,
771
+ _strict_response_validation=_strict_response_validation,
772
+ )
773
+ self._client = httpx.Client(
774
+ base_url=base_url,
775
+ timeout=timeout,
776
+ proxies=proxies, # type: ignore
777
+ transport=transport, # type: ignore
778
+ limits=limits,
779
+ headers={"Accept": "application/json"},
780
+ )
781
+
782
+ @overload
783
+ def request(
784
+ self,
785
+ cast_to: Type[ResponseT],
786
+ options: FinalRequestOptions,
787
+ remaining_retries: Optional[int] = None,
788
+ *,
789
+ stream: Literal[True],
790
+ ) -> Stream[ResponseT]:
791
+ ...
792
+
793
+ @overload
794
+ def request(
795
+ self,
796
+ cast_to: Type[ResponseT],
797
+ options: FinalRequestOptions,
798
+ remaining_retries: Optional[int] = None,
799
+ *,
800
+ stream: Literal[False] = False,
801
+ ) -> ResponseT:
802
+ ...
803
+
804
+ @overload
805
+ def request(
806
+ self,
807
+ cast_to: Type[ResponseT],
808
+ options: FinalRequestOptions,
809
+ remaining_retries: Optional[int] = None,
810
+ *,
811
+ stream: bool = False,
812
+ ) -> ResponseT | Stream[ResponseT]:
813
+ ...
814
+
815
+ def request(
816
+ self,
817
+ cast_to: Type[ResponseT],
818
+ options: FinalRequestOptions,
819
+ remaining_retries: Optional[int] = None,
820
+ *,
821
+ stream: bool = False,
822
+ ) -> ResponseT | Stream[ResponseT]:
823
+ return self._request(
824
+ cast_to=cast_to,
825
+ options=options,
826
+ stream=stream,
827
+ remaining_retries=remaining_retries,
828
+ )
829
+
830
+ def _request(
831
+ self,
832
+ *,
833
+ cast_to: Type[ResponseT],
834
+ options: FinalRequestOptions,
835
+ remaining_retries: int | None,
836
+ stream: bool,
837
+ ) -> ResponseT | Stream[ResponseT]:
838
+ retries = self._remaining_retries(remaining_retries, options)
839
+ request = self._build_request(options)
840
+
841
+ try:
842
+ response = self._client.send(request, auth=self.custom_auth, stream=stream)
843
+ response.raise_for_status()
844
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
845
+ if retries > 0 and self._should_retry(err.response):
846
+ return self._retry_request(options, cast_to, retries, err.response.headers, stream=stream)
847
+
848
+ # If the response is streamed then we need to explicitly read the response
849
+ # to completion before attempting to access the response text.
850
+ err.response.read()
851
+ raise self._make_status_error_from_response(request, err.response) from None
852
+ except httpx.TimeoutException as err:
853
+ if retries > 0:
854
+ return self._retry_request(options, cast_to, retries, stream=stream)
855
+ raise APITimeoutError(request=request) from err
856
+ except Exception as err:
857
+ if retries > 0:
858
+ return self._retry_request(options, cast_to, retries, stream=stream)
859
+ raise APIConnectionError(request=request) from err
860
+
861
+ if stream:
862
+ return Stream(cast_to=cast_to, response=response, client=self)
863
+
864
+ try:
865
+ rsp = self._process_response(cast_to=cast_to, options=options, response=response)
866
+ except pydantic.ValidationError as err:
867
+ raise APIResponseValidationError(request=request, response=response) from err
868
+
869
+ return rsp
870
+
871
+ def _retry_request(
872
+ self,
873
+ options: FinalRequestOptions,
874
+ cast_to: Type[ResponseT],
875
+ remaining_retries: int,
876
+ response_headers: Optional[httpx.Headers] = None,
877
+ *,
878
+ stream: bool,
879
+ ) -> ResponseT | Stream[ResponseT]:
880
+ remaining = remaining_retries - 1
881
+ timeout = self._calculate_retry_timeout(remaining, options, response_headers)
882
+
883
+ # In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a
884
+ # different thread if necessary.
885
+ time.sleep(timeout)
886
+
887
+ return self._request(
888
+ options=options,
889
+ cast_to=cast_to,
890
+ remaining_retries=remaining,
891
+ stream=stream,
892
+ )
893
+
894
+ def _request_api_list(
895
+ self,
896
+ model: Type[ModelT],
897
+ page: Type[SyncPageT],
898
+ options: FinalRequestOptions,
899
+ ) -> SyncPageT:
900
+ resp = cast(SyncPageT, self.request(page, options, stream=False))
901
+ resp._set_private_attributes( # pyright: ignore[reportPrivateUsage]
902
+ client=self,
903
+ model=model,
904
+ options=options,
905
+ )
906
+ return resp
907
+
908
+ def get(
909
+ self,
910
+ path: str,
911
+ *,
912
+ cast_to: Type[ResponseT],
913
+ options: RequestOptions = {},
914
+ ) -> ResponseT:
915
+ opts = FinalRequestOptions.construct(method="get", url=path, **options)
916
+ # cast is required because mypy complains about returning Any even though
917
+ # it understands the type variables
918
+ return cast(ResponseT, self.request(cast_to, opts, stream=False))
919
+
920
+ @overload
921
+ def post(
922
+ self,
923
+ path: str,
924
+ *,
925
+ cast_to: Type[ResponseT],
926
+ body: Body | None = None,
927
+ options: RequestOptions = {},
928
+ files: RequestFiles | None = None,
929
+ stream: Literal[False] = False,
930
+ ) -> ResponseT:
931
+ ...
932
+
933
+ @overload
934
+ def post(
935
+ self,
936
+ path: str,
937
+ *,
938
+ cast_to: Type[ResponseT],
939
+ body: Body | None = None,
940
+ options: RequestOptions = {},
941
+ files: RequestFiles | None = None,
942
+ stream: Literal[True],
943
+ ) -> Stream[ResponseT]:
944
+ ...
945
+
946
+ @overload
947
+ def post(
948
+ self,
949
+ path: str,
950
+ *,
951
+ cast_to: Type[ResponseT],
952
+ body: Body | None = None,
953
+ options: RequestOptions = {},
954
+ files: RequestFiles | None = None,
955
+ stream: bool,
956
+ ) -> ResponseT | Stream[ResponseT]:
957
+ ...
958
+
959
+ def post(
960
+ self,
961
+ path: str,
962
+ *,
963
+ cast_to: Type[ResponseT],
964
+ body: Body | None = None,
965
+ options: RequestOptions = {},
966
+ files: RequestFiles | None = None,
967
+ stream: bool = False,
968
+ ) -> ResponseT | Stream[ResponseT]:
969
+ opts = FinalRequestOptions.construct(method="post", url=path, json_data=body, files=files, **options)
970
+ return cast(ResponseT, self.request(cast_to, opts, stream=stream))
971
+
972
+ def patch(
973
+ self,
974
+ path: str,
975
+ *,
976
+ cast_to: Type[ResponseT],
977
+ body: Body | None = None,
978
+ options: RequestOptions = {},
979
+ ) -> ResponseT:
980
+ opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
981
+ return cast(ResponseT, self.request(cast_to, opts))
982
+
983
+ def put(
984
+ self,
985
+ path: str,
986
+ *,
987
+ cast_to: Type[ResponseT],
988
+ body: Body | None = None,
989
+ files: RequestFiles | None = None,
990
+ options: RequestOptions = {},
991
+ ) -> ResponseT:
992
+ opts = FinalRequestOptions.construct(method="put", url=path, json_data=body, files=files, **options)
993
+ return cast(ResponseT, self.request(cast_to, opts))
994
+
995
+ def delete(
996
+ self,
997
+ path: str,
998
+ *,
999
+ cast_to: Type[ResponseT],
1000
+ body: Body | None = None,
1001
+ options: RequestOptions = {},
1002
+ ) -> ResponseT:
1003
+ opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options)
1004
+ return cast(ResponseT, self.request(cast_to, opts))
1005
+
1006
+ def get_api_list(
1007
+ self,
1008
+ path: str,
1009
+ *,
1010
+ model: Type[ModelT],
1011
+ page: Type[SyncPageT],
1012
+ body: Body | None = None,
1013
+ options: RequestOptions = {},
1014
+ method: str = "get",
1015
+ ) -> SyncPageT:
1016
+ opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options)
1017
+ return self._request_api_list(model, page, opts)
1018
+
1019
+
1020
+ class AsyncAPIClient(BaseClient):
1021
+ _client: httpx.AsyncClient
1022
+
1023
+ def __init__(
1024
+ self,
1025
+ *,
1026
+ version: str,
1027
+ base_url: str,
1028
+ _strict_response_validation: bool,
1029
+ max_retries: int = DEFAULT_MAX_RETRIES,
1030
+ timeout: float | Timeout | None = DEFAULT_TIMEOUT,
1031
+ transport: Transport | None = None,
1032
+ proxies: ProxiesTypes | None = None,
1033
+ limits: Limits | None = DEFAULT_LIMITS,
1034
+ custom_headers: Mapping[str, str] | None = None,
1035
+ custom_query: Mapping[str, object] | None = None,
1036
+ ) -> None:
1037
+ limits = limits or DEFAULT_LIMITS
1038
+ super().__init__(
1039
+ version=version,
1040
+ limits=limits,
1041
+ timeout=timeout,
1042
+ max_retries=max_retries,
1043
+ custom_query=custom_query,
1044
+ custom_headers=custom_headers,
1045
+ _strict_response_validation=_strict_response_validation,
1046
+ )
1047
+ self._client = httpx.AsyncClient(
1048
+ base_url=base_url,
1049
+ timeout=timeout,
1050
+ proxies=proxies, # type: ignore
1051
+ transport=transport, # type: ignore
1052
+ limits=limits,
1053
+ headers={"Accept": "application/json"},
1054
+ )
1055
+
1056
+ @overload
1057
+ async def request(
1058
+ self,
1059
+ cast_to: Type[ResponseT],
1060
+ options: FinalRequestOptions,
1061
+ *,
1062
+ stream: Literal[False] = False,
1063
+ remaining_retries: Optional[int] = None,
1064
+ ) -> ResponseT:
1065
+ ...
1066
+
1067
+ @overload
1068
+ async def request(
1069
+ self,
1070
+ cast_to: Type[ResponseT],
1071
+ options: FinalRequestOptions,
1072
+ *,
1073
+ stream: Literal[True],
1074
+ remaining_retries: Optional[int] = None,
1075
+ ) -> AsyncStream[ResponseT]:
1076
+ ...
1077
+
1078
+ @overload
1079
+ async def request(
1080
+ self,
1081
+ cast_to: Type[ResponseT],
1082
+ options: FinalRequestOptions,
1083
+ *,
1084
+ stream: bool,
1085
+ remaining_retries: Optional[int] = None,
1086
+ ) -> ResponseT | AsyncStream[ResponseT]:
1087
+ ...
1088
+
1089
+ async def request(
1090
+ self,
1091
+ cast_to: Type[ResponseT],
1092
+ options: FinalRequestOptions,
1093
+ *,
1094
+ stream: bool = False,
1095
+ remaining_retries: Optional[int] = None,
1096
+ ) -> ResponseT | AsyncStream[ResponseT]:
1097
+ return await self._request(
1098
+ cast_to=cast_to,
1099
+ options=options,
1100
+ stream=stream,
1101
+ remaining_retries=remaining_retries,
1102
+ )
1103
+
1104
+ async def _request(
1105
+ self,
1106
+ cast_to: Type[ResponseT],
1107
+ options: FinalRequestOptions,
1108
+ *,
1109
+ stream: bool,
1110
+ remaining_retries: int | None,
1111
+ ) -> ResponseT | AsyncStream[ResponseT]:
1112
+ retries = self._remaining_retries(remaining_retries, options)
1113
+ request = self._build_request(options)
1114
+
1115
+ try:
1116
+ response = await self._client.send(request, auth=self.custom_auth, stream=stream)
1117
+ response.raise_for_status()
1118
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1119
+ if retries > 0 and self._should_retry(err.response):
1120
+ return await self._retry_request(options, cast_to, retries, err.response.headers, stream=stream)
1121
+
1122
+ # If the response is streamed then we need to explicitly read the response
1123
+ # to completion before attempting to access the response text.
1124
+ await err.response.aread()
1125
+ raise self._make_status_error_from_response(request, err.response) from None
1126
+ except httpx.ConnectTimeout as err:
1127
+ if retries > 0:
1128
+ return await self._retry_request(options, cast_to, retries, stream=stream)
1129
+ raise APITimeoutError(request=request) from err
1130
+ except httpx.ReadTimeout as err:
1131
+ # We explicitly do not retry on ReadTimeout errors as this means
1132
+ # that the server processing the request has taken 60 seconds
1133
+ # (our default timeout). This likely indicates that something
1134
+ # is not working as expected on the server side.
1135
+ raise
1136
+ except httpx.TimeoutException as err:
1137
+ if retries > 0:
1138
+ return await self._retry_request(options, cast_to, retries, stream=stream)
1139
+ raise APITimeoutError(request=request) from err
1140
+ except Exception as err:
1141
+ if retries > 0:
1142
+ return await self._retry_request(options, cast_to, retries, stream=stream)
1143
+ raise APIConnectionError(request=request) from err
1144
+
1145
+ if stream:
1146
+ return AsyncStream(cast_to=cast_to, response=response, client=self)
1147
+
1148
+ try:
1149
+ rsp = self._process_response(cast_to=cast_to, options=options, response=response)
1150
+ except pydantic.ValidationError as err:
1151
+ raise APIResponseValidationError(request=request, response=response) from err
1152
+
1153
+ return rsp
1154
+
1155
+ async def _retry_request(
1156
+ self,
1157
+ options: FinalRequestOptions,
1158
+ cast_to: Type[ResponseT],
1159
+ remaining_retries: int,
1160
+ response_headers: Optional[httpx.Headers] = None,
1161
+ *,
1162
+ stream: bool,
1163
+ ) -> ResponseT | AsyncStream[ResponseT]:
1164
+ remaining = remaining_retries - 1
1165
+ timeout = self._calculate_retry_timeout(remaining, options, response_headers)
1166
+
1167
+ await anyio.sleep(timeout)
1168
+
1169
+ return await self._request(
1170
+ options=options,
1171
+ cast_to=cast_to,
1172
+ remaining_retries=remaining,
1173
+ stream=stream,
1174
+ )
1175
+
1176
+ def _request_api_list(
1177
+ self,
1178
+ model: Type[ModelT],
1179
+ page: Type[AsyncPageT],
1180
+ options: FinalRequestOptions,
1181
+ ) -> AsyncPaginator[ModelT, AsyncPageT]:
1182
+ return AsyncPaginator(client=self, options=options, page_cls=page, model=model)
1183
+
1184
+ async def get(
1185
+ self,
1186
+ path: str,
1187
+ *,
1188
+ cast_to: Type[ResponseT],
1189
+ options: RequestOptions = {},
1190
+ ) -> ResponseT:
1191
+ opts = FinalRequestOptions.construct(method="get", url=path, **options)
1192
+ return await self.request(cast_to, opts)
1193
+
1194
+ @overload
1195
+ async def post(
1196
+ self,
1197
+ path: str,
1198
+ *,
1199
+ cast_to: Type[ResponseT],
1200
+ body: Body | None = None,
1201
+ files: RequestFiles | None = None,
1202
+ options: RequestOptions = {},
1203
+ stream: Literal[False] = False,
1204
+ ) -> ResponseT:
1205
+ ...
1206
+
1207
+ @overload
1208
+ async def post(
1209
+ self,
1210
+ path: str,
1211
+ *,
1212
+ cast_to: Type[ResponseT],
1213
+ body: Body | None = None,
1214
+ files: RequestFiles | None = None,
1215
+ options: RequestOptions = {},
1216
+ stream: Literal[True],
1217
+ ) -> AsyncStream[ResponseT]:
1218
+ ...
1219
+
1220
+ @overload
1221
+ async def post(
1222
+ self,
1223
+ path: str,
1224
+ *,
1225
+ cast_to: Type[ResponseT],
1226
+ body: Body | None = None,
1227
+ files: RequestFiles | None = None,
1228
+ options: RequestOptions = {},
1229
+ stream: bool,
1230
+ ) -> ResponseT | AsyncStream[ResponseT]:
1231
+ ...
1232
+
1233
+ async def post(
1234
+ self,
1235
+ path: str,
1236
+ *,
1237
+ cast_to: Type[ResponseT],
1238
+ body: Body | None = None,
1239
+ files: RequestFiles | None = None,
1240
+ options: RequestOptions = {},
1241
+ stream: bool = False,
1242
+ ) -> ResponseT | AsyncStream[ResponseT]:
1243
+ opts = FinalRequestOptions.construct(method="post", url=path, json_data=body, files=files, **options)
1244
+ return await self.request(cast_to, opts, stream=stream)
1245
+
1246
+ async def patch(
1247
+ self,
1248
+ path: str,
1249
+ *,
1250
+ cast_to: Type[ResponseT],
1251
+ body: Body | None = None,
1252
+ options: RequestOptions = {},
1253
+ ) -> ResponseT:
1254
+ opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
1255
+ return await self.request(cast_to, opts)
1256
+
1257
+ async def put(
1258
+ self,
1259
+ path: str,
1260
+ *,
1261
+ cast_to: Type[ResponseT],
1262
+ body: Body | None = None,
1263
+ files: RequestFiles | None = None,
1264
+ options: RequestOptions = {},
1265
+ ) -> ResponseT:
1266
+ opts = FinalRequestOptions.construct(method="put", url=path, json_data=body, files=files, **options)
1267
+ return await self.request(cast_to, opts)
1268
+
1269
+ async def delete(
1270
+ self,
1271
+ path: str,
1272
+ *,
1273
+ cast_to: Type[ResponseT],
1274
+ body: Body | None = None,
1275
+ options: RequestOptions = {},
1276
+ ) -> ResponseT:
1277
+ opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options)
1278
+ return await self.request(cast_to, opts)
1279
+
1280
+ def get_api_list(
1281
+ self,
1282
+ path: str,
1283
+ *,
1284
+ # TODO: support paginating `str`
1285
+ model: Type[ModelT],
1286
+ page: Type[AsyncPageT],
1287
+ body: Body | None = None,
1288
+ options: RequestOptions = {},
1289
+ method: str = "get",
1290
+ ) -> AsyncPaginator[ModelT, AsyncPageT]:
1291
+ opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options)
1292
+ return self._request_api_list(model, page, opts)
1293
+
1294
+
1295
+ def make_request_options(
1296
+ *,
1297
+ query: Query | None = None,
1298
+ extra_headers: Headers | None = None,
1299
+ extra_query: Query | None = None,
1300
+ extra_body: Body | None = None,
1301
+ idempotency_key: str | None = None,
1302
+ timeout: float | None | NotGiven = NOT_GIVEN,
1303
+ ) -> RequestOptions:
1304
+ """Create a dict of type RequestOptions without keys of NotGiven values."""
1305
+ options: RequestOptions = {}
1306
+ if extra_headers is not None:
1307
+ options["headers"] = extra_headers
1308
+
1309
+ if extra_body is not None:
1310
+ options["extra_json"] = cast(AnyMapping, extra_body)
1311
+
1312
+ if query is not None:
1313
+ options["params"] = query
1314
+
1315
+ if extra_query is not None:
1316
+ options["params"] = {**options.get("params", {}), **extra_query}
1317
+
1318
+ if not isinstance(timeout, NotGiven):
1319
+ options["timeout"] = timeout
1320
+
1321
+ if idempotency_key is not None:
1322
+ options["idempotency_key"] = idempotency_key
1323
+
1324
+ return options
1325
+
1326
+
1327
+ class OtherPlatform:
1328
+ def __init__(self, name: str) -> None:
1329
+ self.name = name
1330
+
1331
+ def __str__(self) -> str:
1332
+ return f"Other:{self.name}"
1333
+
1334
+
1335
+ Platform = Union[
1336
+ OtherPlatform,
1337
+ Literal[
1338
+ "MacOS",
1339
+ "Linux",
1340
+ "Windows",
1341
+ "FreeBSD",
1342
+ "OpenBSD",
1343
+ "iOS",
1344
+ "Android",
1345
+ "Unknown",
1346
+ ],
1347
+ ]
1348
+
1349
+
1350
+ def get_platform() -> Platform:
1351
+ system = platform.system().lower()
1352
+ platform_name = platform.platform().lower()
1353
+ if "iphone" in platform_name or "ipad" in platform_name:
1354
+ # Tested using Python3IDE on an iPhone 11 and Pythonista on an iPad 7
1355
+ # system is Darwin and platform_name is a string like:
1356
+ # - Darwin-21.6.0-iPhone12,1-64bit
1357
+ # - Darwin-21.6.0-iPad7,11-64bit
1358
+ return "iOS"
1359
+
1360
+ if system == "darwin":
1361
+ return "MacOS"
1362
+
1363
+ if system == "windows":
1364
+ return "Windows"
1365
+
1366
+ if "android" in platform_name:
1367
+ # Tested using Pydroid 3
1368
+ # system is Linux and platform_name is a string like 'Linux-5.10.81-android12-9-00001-geba40aecb3b7-ab8534902-aarch64-with-libc'
1369
+ return "Android"
1370
+
1371
+ if system == "linux":
1372
+ # https://distro.readthedocs.io/en/latest/#distro.id
1373
+ distro_id = distro.id()
1374
+ if distro_id == "freebsd":
1375
+ return "FreeBSD"
1376
+
1377
+ if distro_id == "openbsd":
1378
+ return "OpenBSD"
1379
+
1380
+ return "Linux"
1381
+
1382
+ if platform_name:
1383
+ return OtherPlatform(platform_name)
1384
+
1385
+ return "Unknown"
1386
+
1387
+
1388
+ class OtherArch:
1389
+ def __init__(self, name: str) -> None:
1390
+ self.name = name
1391
+
1392
+ def __str__(self) -> str:
1393
+ return f"other:{self.name}"
1394
+
1395
+
1396
+ Arch = Union[OtherArch, Literal["x32", "x64", "arm", "arm64", "unknown"]]
1397
+
1398
+
1399
+ def get_architecture() -> Arch:
1400
+ python_bitness, _ = platform.architecture()
1401
+ machine = platform.machine().lower()
1402
+ if machine in ("arm64", "aarch64"):
1403
+ return "arm64"
1404
+
1405
+ # TODO: untested
1406
+ if machine == "arm":
1407
+ return "arm"
1408
+
1409
+ if machine == "x86_64":
1410
+ return "x64"
1411
+
1412
+ # TODO: untested
1413
+ if python_bitness == "32bit":
1414
+ return "x32"
1415
+
1416
+ if machine:
1417
+ return OtherArch(machine)
1418
+
1419
+ return "unknown"
1420
+
1421
+
1422
+ def _merge_mappings(
1423
+ obj1: Mapping[_T_co, Union[_T, Omit]],
1424
+ obj2: Mapping[_T_co, Union[_T, Omit]],
1425
+ ) -> Dict[_T_co, _T]:
1426
+ """Merge two mappings of the same type, removing any values that are instances of `Omit`.
1427
+
1428
+ In cases with duplicate keys the second mapping takes precedence.
1429
+ """
1430
+ merged = {**obj1, **obj2}
1431
+ return {key: value for key, value in merged.items() if not isinstance(value, Omit)}