@xyd-js/opensdk-python 0.0.0-build-f0c10f6-20260703195526

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 (539) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__create/input.json +325 -0
  4. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__create/output.py +26 -0
  5. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__delete/input.json +201 -0
  6. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__delete/output.py +28 -0
  7. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__list/input.json +400 -0
  8. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__list/output.py +29 -0
  9. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__retrieve/input.json +304 -0
  10. package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__retrieve/output.py +28 -0
  11. package/__fixtures__/-2.complex.openai/admin__organization__audit_logs__list/input.json +2602 -0
  12. package/__fixtures__/-2.complex.openai/admin__organization__audit_logs__list/output.py +29 -0
  13. package/__fixtures__/-2.complex.openai/admin__organization__certificates__activate__create/input.json +308 -0
  14. package/__fixtures__/-2.complex.openai/admin__organization__certificates__activate__create/output.py +32 -0
  15. package/__fixtures__/-2.complex.openai/admin__organization__certificates__create/input.json +308 -0
  16. package/__fixtures__/-2.complex.openai/admin__organization__certificates__create/output.py +28 -0
  17. package/__fixtures__/-2.complex.openai/admin__organization__certificates__deactivate__create/input.json +308 -0
  18. package/__fixtures__/-2.complex.openai/admin__organization__certificates__deactivate__create/output.py +32 -0
  19. package/__fixtures__/-2.complex.openai/admin__organization__certificates__delete/input.json +196 -0
  20. package/__fixtures__/-2.complex.openai/admin__organization__certificates__delete/output.py +28 -0
  21. package/__fixtures__/-2.complex.openai/admin__organization__certificates__list/input.json +356 -0
  22. package/__fixtures__/-2.complex.openai/admin__organization__certificates__list/output.py +29 -0
  23. package/__fixtures__/-2.complex.openai/admin__organization__certificates__retrieve/input.json +300 -0
  24. package/__fixtures__/-2.complex.openai/admin__organization__certificates__retrieve/output.py +30 -0
  25. package/__fixtures__/-2.complex.openai/admin__organization__certificates__update/input.json +310 -0
  26. package/__fixtures__/-2.complex.openai/admin__organization__certificates__update/output.py +30 -0
  27. package/__fixtures__/-2.complex.openai/admin__organization__costs__list/input.json +1062 -0
  28. package/__fixtures__/-2.complex.openai/admin__organization__costs__list/output.py +29 -0
  29. package/__fixtures__/-2.complex.openai/admin__organization__groups__create/input.json +239 -0
  30. package/__fixtures__/-2.complex.openai/admin__organization__groups__create/output.py +26 -0
  31. package/__fixtures__/-2.complex.openai/admin__organization__groups__delete/input.json +206 -0
  32. package/__fixtures__/-2.complex.openai/admin__organization__groups__delete/output.py +28 -0
  33. package/__fixtures__/-2.complex.openai/admin__organization__groups__list/input.json +316 -0
  34. package/__fixtures__/-2.complex.openai/admin__organization__groups__list/output.py +29 -0
  35. package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__create/input.json +364 -0
  36. package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__create/output.py +34 -0
  37. package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__delete/input.json +210 -0
  38. package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__delete/output.py +36 -0
  39. package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__list/input.json +398 -0
  40. package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__list/output.py +37 -0
  41. package/__fixtures__/-2.complex.openai/admin__organization__groups__update/input.json +241 -0
  42. package/__fixtures__/-2.complex.openai/admin__organization__groups__update/output.py +28 -0
  43. package/__fixtures__/-2.complex.openai/admin__organization__groups__users__create/input.json +237 -0
  44. package/__fixtures__/-2.complex.openai/admin__organization__groups__users__create/output.py +34 -0
  45. package/__fixtures__/-2.complex.openai/admin__organization__groups__users__delete/input.json +211 -0
  46. package/__fixtures__/-2.complex.openai/admin__organization__groups__users__delete/output.py +36 -0
  47. package/__fixtures__/-2.complex.openai/admin__organization__groups__users__list/input.json +314 -0
  48. package/__fixtures__/-2.complex.openai/admin__organization__groups__users__list/output.py +37 -0
  49. package/__fixtures__/-2.complex.openai/admin__organization__invites__create/input.json +386 -0
  50. package/__fixtures__/-2.complex.openai/admin__organization__invites__create/output.py +28 -0
  51. package/__fixtures__/-2.complex.openai/admin__organization__invites__delete/input.json +203 -0
  52. package/__fixtures__/-2.complex.openai/admin__organization__invites__delete/output.py +28 -0
  53. package/__fixtures__/-2.complex.openai/admin__organization__invites__list/input.json +414 -0
  54. package/__fixtures__/-2.complex.openai/admin__organization__invites__list/output.py +29 -0
  55. package/__fixtures__/-2.complex.openai/admin__organization__invites__retrieve/input.json +337 -0
  56. package/__fixtures__/-2.complex.openai/admin__organization__invites__retrieve/output.py +28 -0
  57. package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__delete/input.json +279 -0
  58. package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__delete/output.py +36 -0
  59. package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__list/input.json +475 -0
  60. package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__list/output.py +37 -0
  61. package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__retrieve/input.json +400 -0
  62. package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__retrieve/output.py +36 -0
  63. package/__fixtures__/-2.complex.openai/admin__organization__projects__archive/input.json +247 -0
  64. package/__fixtures__/-2.complex.openai/admin__organization__projects__archive/output.py +28 -0
  65. package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__activate__create/input.json +324 -0
  66. package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__activate__create/output.py +40 -0
  67. package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__deactivate__create/input.json +324 -0
  68. package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__deactivate__create/output.py +40 -0
  69. package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__list/input.json +372 -0
  70. package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__list/output.py +37 -0
  71. package/__fixtures__/-2.complex.openai/admin__organization__projects__create/input.json +281 -0
  72. package/__fixtures__/-2.complex.openai/admin__organization__projects__create/output.py +28 -0
  73. package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__create/input.json +274 -0
  74. package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__create/output.py +34 -0
  75. package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__delete/input.json +211 -0
  76. package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__delete/output.py +36 -0
  77. package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__list/input.json +342 -0
  78. package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__list/output.py +37 -0
  79. package/__fixtures__/-2.complex.openai/admin__organization__projects__list/input.json +330 -0
  80. package/__fixtures__/-2.complex.openai/admin__organization__projects__list/output.py +29 -0
  81. package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__list_rate_limits/input.json +358 -0
  82. package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__list_rate_limits/output.py +37 -0
  83. package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__update_rate_limit/input.json +407 -0
  84. package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__update_rate_limit/output.py +38 -0
  85. package/__fixtures__/-2.complex.openai/admin__organization__projects__retrieve/input.json +247 -0
  86. package/__fixtures__/-2.complex.openai/admin__organization__projects__retrieve/output.py +28 -0
  87. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__create/input.json +372 -0
  88. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__create/output.py +34 -0
  89. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__delete/input.json +216 -0
  90. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__delete/output.py +36 -0
  91. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__list/input.json +391 -0
  92. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__list/output.py +37 -0
  93. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__retrieve/input.json +253 -0
  94. package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__retrieve/output.py +36 -0
  95. package/__fixtures__/-2.complex.openai/admin__organization__projects__update/input.json +356 -0
  96. package/__fixtures__/-2.complex.openai/admin__organization__projects__update/output.py +30 -0
  97. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__create/input.json +349 -0
  98. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__create/output.py +36 -0
  99. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__delete/input.json +279 -0
  100. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__delete/output.py +36 -0
  101. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__list/input.json +387 -0
  102. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__list/output.py +37 -0
  103. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__retrieve/input.json +250 -0
  104. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__retrieve/output.py +36 -0
  105. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__update/input.json +339 -0
  106. package/__fixtures__/-2.complex.openai/admin__organization__projects__users__update/output.py +38 -0
  107. package/__fixtures__/-2.complex.openai/admin__organization__roles__create/input.json +283 -0
  108. package/__fixtures__/-2.complex.openai/admin__organization__roles__create/output.py +28 -0
  109. package/__fixtures__/-2.complex.openai/admin__organization__roles__delete/input.json +206 -0
  110. package/__fixtures__/-2.complex.openai/admin__organization__roles__delete/output.py +28 -0
  111. package/__fixtures__/-2.complex.openai/admin__organization__roles__list/input.json +338 -0
  112. package/__fixtures__/-2.complex.openai/admin__organization__roles__list/output.py +29 -0
  113. package/__fixtures__/-2.complex.openai/admin__organization__roles__update/input.json +296 -0
  114. package/__fixtures__/-2.complex.openai/admin__organization__roles__update/output.py +30 -0
  115. package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_speeches__list/input.json +1108 -0
  116. package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_speeches__list/output.py +35 -0
  117. package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_transcriptions__list/input.json +1108 -0
  118. package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_transcriptions__list/output.py +35 -0
  119. package/__fixtures__/-2.complex.openai/admin__organization__usage__code_interpreter_sessions__list/input.json +1054 -0
  120. package/__fixtures__/-2.complex.openai/admin__organization__usage__code_interpreter_sessions__list/output.py +35 -0
  121. package/__fixtures__/-2.complex.openai/admin__organization__usage__completions__list/input.json +1123 -0
  122. package/__fixtures__/-2.complex.openai/admin__organization__usage__completions__list/output.py +35 -0
  123. package/__fixtures__/-2.complex.openai/admin__organization__usage__embeddings__list/input.json +1108 -0
  124. package/__fixtures__/-2.complex.openai/admin__organization__usage__embeddings__list/output.py +35 -0
  125. package/__fixtures__/-2.complex.openai/admin__organization__usage__images__list/input.json +1176 -0
  126. package/__fixtures__/-2.complex.openai/admin__organization__usage__images__list/output.py +35 -0
  127. package/__fixtures__/-2.complex.openai/admin__organization__usage__moderations__list/input.json +1108 -0
  128. package/__fixtures__/-2.complex.openai/admin__organization__usage__moderations__list/output.py +35 -0
  129. package/__fixtures__/-2.complex.openai/admin__organization__usage__vector_stores__list/input.json +1054 -0
  130. package/__fixtures__/-2.complex.openai/admin__organization__usage__vector_stores__list/output.py +35 -0
  131. package/__fixtures__/-2.complex.openai/admin__organization__users__delete/input.json +202 -0
  132. package/__fixtures__/-2.complex.openai/admin__organization__users__delete/output.py +28 -0
  133. package/__fixtures__/-2.complex.openai/admin__organization__users__list/input.json +557 -0
  134. package/__fixtures__/-2.complex.openai/admin__organization__users__list/output.py +29 -0
  135. package/__fixtures__/-2.complex.openai/admin__organization__users__retrieve/input.json +472 -0
  136. package/__fixtures__/-2.complex.openai/admin__organization__users__retrieve/output.py +28 -0
  137. package/__fixtures__/-2.complex.openai/admin__organization__users__roles__create/input.json +611 -0
  138. package/__fixtures__/-2.complex.openai/admin__organization__users__roles__create/output.py +34 -0
  139. package/__fixtures__/-2.complex.openai/admin__organization__users__roles__delete/input.json +210 -0
  140. package/__fixtures__/-2.complex.openai/admin__organization__users__roles__delete/output.py +36 -0
  141. package/__fixtures__/-2.complex.openai/admin__organization__users__roles__list/input.json +398 -0
  142. package/__fixtures__/-2.complex.openai/admin__organization__users__roles__list/output.py +37 -0
  143. package/__fixtures__/-2.complex.openai/admin__organization__users__update/input.json +528 -0
  144. package/__fixtures__/-2.complex.openai/admin__organization__users__update/output.py +30 -0
  145. package/__fixtures__/-2.complex.openai/audio__speech__create/input.json +388 -0
  146. package/__fixtures__/-2.complex.openai/audio__speech__create/output.py +22 -0
  147. package/__fixtures__/-2.complex.openai/audio__transcriptions__create/input.json +999 -0
  148. package/__fixtures__/-2.complex.openai/audio__transcriptions__create/output.py +22 -0
  149. package/__fixtures__/-2.complex.openai/audio__translations__create/input.json +430 -0
  150. package/__fixtures__/-2.complex.openai/audio__translations__create/output.py +22 -0
  151. package/__fixtures__/-2.complex.openai/audio__voice_consents__create/input.json +244 -0
  152. package/__fixtures__/-2.complex.openai/audio__voice_consents__create/output.py +22 -0
  153. package/__fixtures__/-2.complex.openai/audio__voice_consents__delete/input.json +190 -0
  154. package/__fixtures__/-2.complex.openai/audio__voice_consents__delete/output.py +22 -0
  155. package/__fixtures__/-2.complex.openai/audio__voice_consents__list/input.json +285 -0
  156. package/__fixtures__/-2.complex.openai/audio__voice_consents__list/output.py +23 -0
  157. package/__fixtures__/-2.complex.openai/audio__voice_consents__retrieve/input.json +212 -0
  158. package/__fixtures__/-2.complex.openai/audio__voice_consents__retrieve/output.py +22 -0
  159. package/__fixtures__/-2.complex.openai/audio__voice_consents__update/input.json +236 -0
  160. package/__fixtures__/-2.complex.openai/audio__voice_consents__update/output.py +22 -0
  161. package/__fixtures__/-2.complex.openai/audio__voices__create/input.json +235 -0
  162. package/__fixtures__/-2.complex.openai/audio__voices__create/output.py +22 -0
  163. package/__fixtures__/-2.complex.openai/batches__cancel/input.json +594 -0
  164. package/__fixtures__/-2.complex.openai/batches__cancel/output.py +16 -0
  165. package/__fixtures__/-2.complex.openai/batches__create/input.json +701 -0
  166. package/__fixtures__/-2.complex.openai/batches__create/output.py +16 -0
  167. package/__fixtures__/-2.complex.openai/batches__list/input.json +665 -0
  168. package/__fixtures__/-2.complex.openai/batches__list/output.py +17 -0
  169. package/__fixtures__/-2.complex.openai/batches__retrieve/input.json +594 -0
  170. package/__fixtures__/-2.complex.openai/batches__retrieve/output.py +16 -0
  171. package/__fixtures__/-2.complex.openai/beta__assistants__create/input.json +1029 -0
  172. package/__fixtures__/-2.complex.openai/beta__assistants__create/output.py +22 -0
  173. package/__fixtures__/-2.complex.openai/beta__assistants__delete/input.json +190 -0
  174. package/__fixtures__/-2.complex.openai/beta__assistants__delete/output.py +22 -0
  175. package/__fixtures__/-2.complex.openai/beta__assistants__list/input.json +796 -0
  176. package/__fixtures__/-2.complex.openai/beta__assistants__list/output.py +23 -0
  177. package/__fixtures__/-2.complex.openai/beta__assistants__retrieve/input.json +694 -0
  178. package/__fixtures__/-2.complex.openai/beta__assistants__retrieve/output.py +22 -0
  179. package/__fixtures__/-2.complex.openai/beta__assistants__update/input.json +1045 -0
  180. package/__fixtures__/-2.complex.openai/beta__assistants__update/output.py +24 -0
  181. package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__cancel/input.json +482 -0
  182. package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__cancel/output.py +28 -0
  183. package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__create/input.json +738 -0
  184. package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__create/output.py +28 -0
  185. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__delete/input.json +200 -0
  186. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__delete/output.py +28 -0
  187. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__items__list/input.json +1218 -0
  188. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__items__list/output.py +37 -0
  189. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__list/input.json +444 -0
  190. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__list/output.py +29 -0
  191. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__retrieve/input.json +328 -0
  192. package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__retrieve/output.py +28 -0
  193. package/__fixtures__/-2.complex.openai/beta__threads__create/input.json +665 -0
  194. package/__fixtures__/-2.complex.openai/beta__threads__create/output.py +22 -0
  195. package/__fixtures__/-2.complex.openai/beta__threads__delete/input.json +189 -0
  196. package/__fixtures__/-2.complex.openai/beta__threads__delete/output.py +22 -0
  197. package/__fixtures__/-2.complex.openai/beta__threads__messages__create/input.json +938 -0
  198. package/__fixtures__/-2.complex.openai/beta__threads__messages__create/output.py +30 -0
  199. package/__fixtures__/-2.complex.openai/beta__threads__messages__delete/input.json +203 -0
  200. package/__fixtures__/-2.complex.openai/beta__threads__messages__delete/output.py +30 -0
  201. package/__fixtures__/-2.complex.openai/beta__threads__messages__list/input.json +945 -0
  202. package/__fixtures__/-2.complex.openai/beta__threads__messages__list/output.py +31 -0
  203. package/__fixtures__/-2.complex.openai/beta__threads__messages__retrieve/input.json +832 -0
  204. package/__fixtures__/-2.complex.openai/beta__threads__messages__retrieve/output.py +30 -0
  205. package/__fixtures__/-2.complex.openai/beta__threads__messages__update/input.json +855 -0
  206. package/__fixtures__/-2.complex.openai/beta__threads__messages__update/output.py +32 -0
  207. package/__fixtures__/-2.complex.openai/beta__threads__new_and_run/input.json +1899 -0
  208. package/__fixtures__/-2.complex.openai/beta__threads__new_and_run/output.py +22 -0
  209. package/__fixtures__/-2.complex.openai/beta__threads__retrieve/input.json +283 -0
  210. package/__fixtures__/-2.complex.openai/beta__threads__retrieve/output.py +22 -0
  211. package/__fixtures__/-2.complex.openai/beta__threads__runs__cancel/input.json +1181 -0
  212. package/__fixtures__/-2.complex.openai/beta__threads__runs__cancel/output.py +30 -0
  213. package/__fixtures__/-2.complex.openai/beta__threads__runs__create/input.json +1851 -0
  214. package/__fixtures__/-2.complex.openai/beta__threads__runs__create/output.py +30 -0
  215. package/__fixtures__/-2.complex.openai/beta__threads__runs__list/input.json +1285 -0
  216. package/__fixtures__/-2.complex.openai/beta__threads__runs__list/output.py +31 -0
  217. package/__fixtures__/-2.complex.openai/beta__threads__runs__retrieve/input.json +1181 -0
  218. package/__fixtures__/-2.complex.openai/beta__threads__runs__retrieve/output.py +30 -0
  219. package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__list/input.json +1066 -0
  220. package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__list/output.py +39 -0
  221. package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__retrieve/input.json +964 -0
  222. package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__retrieve/output.py +40 -0
  223. package/__fixtures__/-2.complex.openai/beta__threads__runs__submit_tool_outputs__create/input.json +1246 -0
  224. package/__fixtures__/-2.complex.openai/beta__threads__runs__submit_tool_outputs__create/output.py +38 -0
  225. package/__fixtures__/-2.complex.openai/beta__threads__runs__update/input.json +1204 -0
  226. package/__fixtures__/-2.complex.openai/beta__threads__runs__update/output.py +32 -0
  227. package/__fixtures__/-2.complex.openai/beta__threads__update/input.json +315 -0
  228. package/__fixtures__/-2.complex.openai/beta__threads__update/output.py +24 -0
  229. package/__fixtures__/-2.complex.openai/chat__completions__create/input.json +3325 -0
  230. package/__fixtures__/-2.complex.openai/chat__completions__create/output.py +22 -0
  231. package/__fixtures__/-2.complex.openai/chat__completions__delete/input.json +192 -0
  232. package/__fixtures__/-2.complex.openai/chat__completions__delete/output.py +22 -0
  233. package/__fixtures__/-2.complex.openai/chat__completions__list/input.json +1069 -0
  234. package/__fixtures__/-2.complex.openai/chat__completions__list/output.py +23 -0
  235. package/__fixtures__/-2.complex.openai/chat__completions__messages__list/input.json +770 -0
  236. package/__fixtures__/-2.complex.openai/chat__completions__messages__list/output.py +31 -0
  237. package/__fixtures__/-2.complex.openai/chat__completions__retrieve/input.json +938 -0
  238. package/__fixtures__/-2.complex.openai/chat__completions__retrieve/output.py +22 -0
  239. package/__fixtures__/-2.complex.openai/chat__completions__update/input.json +973 -0
  240. package/__fixtures__/-2.complex.openai/chat__completions__update/output.py +22 -0
  241. package/__fixtures__/-2.complex.openai/completions__create/input.json +788 -0
  242. package/__fixtures__/-2.complex.openai/completions__create/output.py +16 -0
  243. package/__fixtures__/-2.complex.openai/containers__create/input.json +671 -0
  244. package/__fixtures__/-2.complex.openai/containers__create/output.py +16 -0
  245. package/__fixtures__/-2.complex.openai/containers__delete/input.json +142 -0
  246. package/__fixtures__/-2.complex.openai/containers__delete/output.py +16 -0
  247. package/__fixtures__/-2.complex.openai/containers__files__content/input.json +154 -0
  248. package/__fixtures__/-2.complex.openai/containers__files__content/output.py +24 -0
  249. package/__fixtures__/-2.complex.openai/containers__files__create/input.json +261 -0
  250. package/__fixtures__/-2.complex.openai/containers__files__create/output.py +24 -0
  251. package/__fixtures__/-2.complex.openai/containers__files__delete/input.json +154 -0
  252. package/__fixtures__/-2.complex.openai/containers__files__delete/output.py +24 -0
  253. package/__fixtures__/-2.complex.openai/containers__files__list/input.json +337 -0
  254. package/__fixtures__/-2.complex.openai/containers__files__list/output.py +25 -0
  255. package/__fixtures__/-2.complex.openai/containers__files__retrieve/input.json +235 -0
  256. package/__fixtures__/-2.complex.openai/containers__files__retrieve/output.py +24 -0
  257. package/__fixtures__/-2.complex.openai/containers__list/input.json +438 -0
  258. package/__fixtures__/-2.complex.openai/containers__list/output.py +17 -0
  259. package/__fixtures__/-2.complex.openai/containers__retrieve/input.json +329 -0
  260. package/__fixtures__/-2.complex.openai/containers__retrieve/output.py +16 -0
  261. package/__fixtures__/-2.complex.openai/conversations__create/input.json +6737 -0
  262. package/__fixtures__/-2.complex.openai/conversations__create/output.py +16 -0
  263. package/__fixtures__/-2.complex.openai/conversations__delete/input.json +186 -0
  264. package/__fixtures__/-2.complex.openai/conversations__delete/output.py +16 -0
  265. package/__fixtures__/-2.complex.openai/conversations__items__create/input.json +8352 -0
  266. package/__fixtures__/-2.complex.openai/conversations__items__create/output.py +25 -0
  267. package/__fixtures__/-2.complex.openai/conversations__items__delete/input.json +213 -0
  268. package/__fixtures__/-2.complex.openai/conversations__items__delete/output.py +24 -0
  269. package/__fixtures__/-2.complex.openai/conversations__items__list/input.json +6695 -0
  270. package/__fixtures__/-2.complex.openai/conversations__items__list/output.py +25 -0
  271. package/__fixtures__/-2.complex.openai/conversations__items__retrieve/input.json +6597 -0
  272. package/__fixtures__/-2.complex.openai/conversations__items__retrieve/output.py +26 -0
  273. package/__fixtures__/-2.complex.openai/conversations__retrieve/input.json +198 -0
  274. package/__fixtures__/-2.complex.openai/conversations__retrieve/output.py +16 -0
  275. package/__fixtures__/-2.complex.openai/conversations__update/input.json +233 -0
  276. package/__fixtures__/-2.complex.openai/conversations__update/output.py +16 -0
  277. package/__fixtures__/-2.complex.openai/embeddings__create/input.json +395 -0
  278. package/__fixtures__/-2.complex.openai/embeddings__create/output.py +16 -0
  279. package/__fixtures__/-2.complex.openai/evals__create/input.json +1424 -0
  280. package/__fixtures__/-2.complex.openai/evals__create/output.py +16 -0
  281. package/__fixtures__/-2.complex.openai/evals__delete/input.json +232 -0
  282. package/__fixtures__/-2.complex.openai/evals__delete/output.py +16 -0
  283. package/__fixtures__/-2.complex.openai/evals__list/input.json +1251 -0
  284. package/__fixtures__/-2.complex.openai/evals__list/output.py +17 -0
  285. package/__fixtures__/-2.complex.openai/evals__retrieve/input.json +1127 -0
  286. package/__fixtures__/-2.complex.openai/evals__retrieve/output.py +16 -0
  287. package/__fixtures__/-2.complex.openai/evals__runs__cancel/input.json +4445 -0
  288. package/__fixtures__/-2.complex.openai/evals__runs__cancel/output.py +24 -0
  289. package/__fixtures__/-2.complex.openai/evals__runs__create/input.json +4526 -0
  290. package/__fixtures__/-2.complex.openai/evals__runs__create/output.py +24 -0
  291. package/__fixtures__/-2.complex.openai/evals__runs__delete/input.json +246 -0
  292. package/__fixtures__/-2.complex.openai/evals__runs__delete/output.py +24 -0
  293. package/__fixtures__/-2.complex.openai/evals__runs__list/input.json +4579 -0
  294. package/__fixtures__/-2.complex.openai/evals__runs__list/output.py +25 -0
  295. package/__fixtures__/-2.complex.openai/evals__runs__output_items__list/input.json +685 -0
  296. package/__fixtures__/-2.complex.openai/evals__runs__output_items__list/output.py +33 -0
  297. package/__fixtures__/-2.complex.openai/evals__runs__output_items__retrieve/input.json +560 -0
  298. package/__fixtures__/-2.complex.openai/evals__runs__output_items__retrieve/output.py +32 -0
  299. package/__fixtures__/-2.complex.openai/evals__runs__retrieve/input.json +4445 -0
  300. package/__fixtures__/-2.complex.openai/evals__runs__retrieve/output.py +24 -0
  301. package/__fixtures__/-2.complex.openai/evals__update/input.json +1160 -0
  302. package/__fixtures__/-2.complex.openai/evals__update/output.py +18 -0
  303. package/__fixtures__/-2.complex.openai/files__content/input.json +151 -0
  304. package/__fixtures__/-2.complex.openai/files__content/output.py +16 -0
  305. package/__fixtures__/-2.complex.openai/files__create/input.json +379 -0
  306. package/__fixtures__/-2.complex.openai/files__create/output.py +16 -0
  307. package/__fixtures__/-2.complex.openai/files__delete/input.json +184 -0
  308. package/__fixtures__/-2.complex.openai/files__delete/output.py +16 -0
  309. package/__fixtures__/-2.complex.openai/files__list/input.json +397 -0
  310. package/__fixtures__/-2.complex.openai/files__list/output.py +17 -0
  311. package/__fixtures__/-2.complex.openai/files__retrieve/input.json +295 -0
  312. package/__fixtures__/-2.complex.openai/files__retrieve/output.py +16 -0
  313. package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__run__create/input.json +1225 -0
  314. package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__run__create/output.py +34 -0
  315. package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__validate__create/input.json +991 -0
  316. package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__validate__create/output.py +32 -0
  317. package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__create/input.json +297 -0
  318. package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__create/output.py +29 -0
  319. package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__delete/input.json +208 -0
  320. package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__delete/output.py +30 -0
  321. package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__list/input.json +325 -0
  322. package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__list/output.py +31 -0
  323. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__cancel/input.json +1645 -0
  324. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__cancel/output.py +22 -0
  325. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__checkpoints__list/input.json +383 -0
  326. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__checkpoints__list/output.py +31 -0
  327. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__create/input.json +1887 -0
  328. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__create/output.py +22 -0
  329. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list/input.json +1714 -0
  330. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list/output.py +23 -0
  331. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list_events/input.json +330 -0
  332. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list_events/output.py +25 -0
  333. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__pause/input.json +1645 -0
  334. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__pause/output.py +22 -0
  335. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__resume/input.json +1645 -0
  336. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__resume/output.py +22 -0
  337. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__retrieve/input.json +1645 -0
  338. package/__fixtures__/-2.complex.openai/fine_tuning__jobs__retrieve/output.py +22 -0
  339. package/__fixtures__/-2.complex.openai/images__edits__create/input.json +744 -0
  340. package/__fixtures__/-2.complex.openai/images__edits__create/output.py +22 -0
  341. package/__fixtures__/-2.complex.openai/images__generations__create/input.json +789 -0
  342. package/__fixtures__/-2.complex.openai/images__generations__create/output.py +22 -0
  343. package/__fixtures__/-2.complex.openai/images__variations__create/input.json +550 -0
  344. package/__fixtures__/-2.complex.openai/images__variations__create/output.py +22 -0
  345. package/__fixtures__/-2.complex.openai/models__delete/input.json +184 -0
  346. package/__fixtures__/-2.complex.openai/models__delete/output.py +16 -0
  347. package/__fixtures__/-2.complex.openai/models__list/input.json +221 -0
  348. package/__fixtures__/-2.complex.openai/models__list/output.py +15 -0
  349. package/__fixtures__/-2.complex.openai/models__retrieve/input.json +199 -0
  350. package/__fixtures__/-2.complex.openai/models__retrieve/output.py +16 -0
  351. package/__fixtures__/-2.complex.openai/moderations__create/input.json +831 -0
  352. package/__fixtures__/-2.complex.openai/moderations__create/output.py +16 -0
  353. package/__fixtures__/-2.complex.openai/projects__groups__roles__create/input.json +368 -0
  354. package/__fixtures__/-2.complex.openai/projects__groups__roles__create/output.py +30 -0
  355. package/__fixtures__/-2.complex.openai/projects__groups__roles__delete/input.json +214 -0
  356. package/__fixtures__/-2.complex.openai/projects__groups__roles__delete/output.py +32 -0
  357. package/__fixtures__/-2.complex.openai/projects__groups__roles__list/input.json +402 -0
  358. package/__fixtures__/-2.complex.openai/projects__groups__roles__list/output.py +33 -0
  359. package/__fixtures__/-2.complex.openai/projects__roles__create/input.json +289 -0
  360. package/__fixtures__/-2.complex.openai/projects__roles__create/output.py +24 -0
  361. package/__fixtures__/-2.complex.openai/projects__roles__delete/input.json +210 -0
  362. package/__fixtures__/-2.complex.openai/projects__roles__delete/output.py +24 -0
  363. package/__fixtures__/-2.complex.openai/projects__roles__list/input.json +344 -0
  364. package/__fixtures__/-2.complex.openai/projects__roles__list/output.py +25 -0
  365. package/__fixtures__/-2.complex.openai/projects__roles__update/input.json +300 -0
  366. package/__fixtures__/-2.complex.openai/projects__roles__update/output.py +26 -0
  367. package/__fixtures__/-2.complex.openai/projects__users__roles__create/input.json +615 -0
  368. package/__fixtures__/-2.complex.openai/projects__users__roles__create/output.py +30 -0
  369. package/__fixtures__/-2.complex.openai/projects__users__roles__delete/input.json +214 -0
  370. package/__fixtures__/-2.complex.openai/projects__users__roles__delete/output.py +32 -0
  371. package/__fixtures__/-2.complex.openai/projects__users__roles__list/input.json +402 -0
  372. package/__fixtures__/-2.complex.openai/projects__users__roles__list/output.py +33 -0
  373. package/__fixtures__/-2.complex.openai/realtime__calls__accept/input.json +1768 -0
  374. package/__fixtures__/-2.complex.openai/realtime__calls__accept/output.py +24 -0
  375. package/__fixtures__/-2.complex.openai/realtime__calls__create/input.json +1790 -0
  376. package/__fixtures__/-2.complex.openai/realtime__calls__create/output.py +22 -0
  377. package/__fixtures__/-2.complex.openai/realtime__calls__hangup/input.json +147 -0
  378. package/__fixtures__/-2.complex.openai/realtime__calls__hangup/output.py +22 -0
  379. package/__fixtures__/-2.complex.openai/realtime__calls__refer/input.json +175 -0
  380. package/__fixtures__/-2.complex.openai/realtime__calls__refer/output.py +22 -0
  381. package/__fixtures__/-2.complex.openai/realtime__calls__reject/input.json +175 -0
  382. package/__fixtures__/-2.complex.openai/realtime__calls__reject/output.py +24 -0
  383. package/__fixtures__/-2.complex.openai/realtime__client_secrets__create/input.json +2407 -0
  384. package/__fixtures__/-2.complex.openai/realtime__client_secrets__create/output.py +22 -0
  385. package/__fixtures__/-2.complex.openai/realtime__sessions__create/input.json +1400 -0
  386. package/__fixtures__/-2.complex.openai/realtime__sessions__create/output.py +22 -0
  387. package/__fixtures__/-2.complex.openai/realtime__transcription_sessions__create/input.json +562 -0
  388. package/__fixtures__/-2.complex.openai/realtime__transcription_sessions__create/output.py +22 -0
  389. package/__fixtures__/-2.complex.openai/realtime__translations__client_secrets__create/input.json +498 -0
  390. package/__fixtures__/-2.complex.openai/realtime__translations__client_secrets__create/output.py +28 -0
  391. package/__fixtures__/-2.complex.openai/responses__cancel/input.json +9526 -0
  392. package/__fixtures__/-2.complex.openai/responses__cancel/output.py +16 -0
  393. package/__fixtures__/-2.complex.openai/responses__compact__create/input.json +8721 -0
  394. package/__fixtures__/-2.complex.openai/responses__compact__create/output.py +22 -0
  395. package/__fixtures__/-2.complex.openai/responses__create/input.json +9862 -0
  396. package/__fixtures__/-2.complex.openai/responses__create/output.py +16 -0
  397. package/__fixtures__/-2.complex.openai/responses__delete/input.json +194 -0
  398. package/__fixtures__/-2.complex.openai/responses__delete/output.py +16 -0
  399. package/__fixtures__/-2.complex.openai/responses__input_items__list/input.json +6686 -0
  400. package/__fixtures__/-2.complex.openai/responses__input_items__list/output.py +25 -0
  401. package/__fixtures__/-2.complex.openai/responses__input_tokens__count/input.json +7368 -0
  402. package/__fixtures__/-2.complex.openai/responses__input_tokens__count/output.py +22 -0
  403. package/__fixtures__/-2.complex.openai/responses__retrieve/input.json +9550 -0
  404. package/__fixtures__/-2.complex.openai/responses__retrieve/output.py +18 -0
  405. package/__fixtures__/-2.complex.openai/skills__content/input.json +152 -0
  406. package/__fixtures__/-2.complex.openai/skills__content/output.py +16 -0
  407. package/__fixtures__/-2.complex.openai/skills__create/input.json +258 -0
  408. package/__fixtures__/-2.complex.openai/skills__create/output.py +14 -0
  409. package/__fixtures__/-2.complex.openai/skills__delete/input.json +186 -0
  410. package/__fixtures__/-2.complex.openai/skills__delete/output.py +16 -0
  411. package/__fixtures__/-2.complex.openai/skills__list/input.json +323 -0
  412. package/__fixtures__/-2.complex.openai/skills__list/output.py +17 -0
  413. package/__fixtures__/-2.complex.openai/skills__retrieve/input.json +226 -0
  414. package/__fixtures__/-2.complex.openai/skills__retrieve/output.py +16 -0
  415. package/__fixtures__/-2.complex.openai/skills__update/input.json +251 -0
  416. package/__fixtures__/-2.complex.openai/skills__update/output.py +16 -0
  417. package/__fixtures__/-2.complex.openai/skills__versions__content/input.json +166 -0
  418. package/__fixtures__/-2.complex.openai/skills__versions__content/output.py +24 -0
  419. package/__fixtures__/-2.complex.openai/skills__versions__create/input.json +284 -0
  420. package/__fixtures__/-2.complex.openai/skills__versions__create/output.py +24 -0
  421. package/__fixtures__/-2.complex.openai/skills__versions__delete/input.json +209 -0
  422. package/__fixtures__/-2.complex.openai/skills__versions__delete/output.py +24 -0
  423. package/__fixtures__/-2.complex.openai/skills__versions__list/input.json +341 -0
  424. package/__fixtures__/-2.complex.openai/skills__versions__list/output.py +25 -0
  425. package/__fixtures__/-2.complex.openai/skills__versions__retrieve/input.json +240 -0
  426. package/__fixtures__/-2.complex.openai/skills__versions__retrieve/output.py +24 -0
  427. package/__fixtures__/-2.complex.openai/uploads__cancel/input.json +407 -0
  428. package/__fixtures__/-2.complex.openai/uploads__cancel/output.py +16 -0
  429. package/__fixtures__/-2.complex.openai/uploads__complete/input.json +443 -0
  430. package/__fixtures__/-2.complex.openai/uploads__complete/output.py +18 -0
  431. package/__fixtures__/-2.complex.openai/uploads__create/input.json +501 -0
  432. package/__fixtures__/-2.complex.openai/uploads__create/output.py +16 -0
  433. package/__fixtures__/-2.complex.openai/uploads__parts__create/input.json +229 -0
  434. package/__fixtures__/-2.complex.openai/uploads__parts__create/output.py +24 -0
  435. package/__fixtures__/-2.complex.openai/vector_stores__create/input.json +507 -0
  436. package/__fixtures__/-2.complex.openai/vector_stores__create/output.py +16 -0
  437. package/__fixtures__/-2.complex.openai/vector_stores__delete/input.json +184 -0
  438. package/__fixtures__/-2.complex.openai/vector_stores__delete/output.py +16 -0
  439. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__cancel/input.json +300 -0
  440. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__cancel/output.py +24 -0
  441. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__create/input.json +314 -0
  442. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__create/output.py +22 -0
  443. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__list_files/input.json +571 -0
  444. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__list_files/output.py +27 -0
  445. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__retrieve/input.json +302 -0
  446. package/__fixtures__/-2.complex.openai/vector_stores__file_batches__retrieve/output.py +24 -0
  447. package/__fixtures__/-2.complex.openai/vector_stores__files__content/input.json +249 -0
  448. package/__fixtures__/-2.complex.openai/vector_stores__files__content/output.py +25 -0
  449. package/__fixtures__/-2.complex.openai/vector_stores__files__create/input.json +527 -0
  450. package/__fixtures__/-2.complex.openai/vector_stores__files__create/output.py +24 -0
  451. package/__fixtures__/-2.complex.openai/vector_stores__files__delete/input.json +198 -0
  452. package/__fixtures__/-2.complex.openai/vector_stores__files__delete/output.py +24 -0
  453. package/__fixtures__/-2.complex.openai/vector_stores__files__list/input.json +562 -0
  454. package/__fixtures__/-2.complex.openai/vector_stores__files__list/output.py +25 -0
  455. package/__fixtures__/-2.complex.openai/vector_stores__files__retrieve/input.json +432 -0
  456. package/__fixtures__/-2.complex.openai/vector_stores__files__retrieve/output.py +24 -0
  457. package/__fixtures__/-2.complex.openai/vector_stores__files__update/input.json +455 -0
  458. package/__fixtures__/-2.complex.openai/vector_stores__files__update/output.py +24 -0
  459. package/__fixtures__/-2.complex.openai/vector_stores__list/input.json +468 -0
  460. package/__fixtures__/-2.complex.openai/vector_stores__list/output.py +17 -0
  461. package/__fixtures__/-2.complex.openai/vector_stores__retrieve/input.json +366 -0
  462. package/__fixtures__/-2.complex.openai/vector_stores__retrieve/output.py +16 -0
  463. package/__fixtures__/-2.complex.openai/vector_stores__search/input.json +637 -0
  464. package/__fixtures__/-2.complex.openai/vector_stores__search/output.py +19 -0
  465. package/__fixtures__/-2.complex.openai/vector_stores__update/input.json +409 -0
  466. package/__fixtures__/-2.complex.openai/vector_stores__update/output.py +18 -0
  467. package/__fixtures__/-2.complex.openai/videos__characters__create/input.json +216 -0
  468. package/__fixtures__/-2.complex.openai/videos__characters__create/output.py +22 -0
  469. package/__fixtures__/-2.complex.openai/videos__characters__retrieve/input.json +193 -0
  470. package/__fixtures__/-2.complex.openai/videos__characters__retrieve/output.py +22 -0
  471. package/__fixtures__/-2.complex.openai/videos__create/input.json +465 -0
  472. package/__fixtures__/-2.complex.openai/videos__create/output.py +16 -0
  473. package/__fixtures__/-2.complex.openai/videos__delete/input.json +190 -0
  474. package/__fixtures__/-2.complex.openai/videos__delete/output.py +16 -0
  475. package/__fixtures__/-2.complex.openai/videos__download_content/input.json +181 -0
  476. package/__fixtures__/-2.complex.openai/videos__download_content/output.py +18 -0
  477. package/__fixtures__/-2.complex.openai/videos__edits__create/input.json +422 -0
  478. package/__fixtures__/-2.complex.openai/videos__edits__create/output.py +20 -0
  479. package/__fixtures__/-2.complex.openai/videos__extensions__create/input.json +446 -0
  480. package/__fixtures__/-2.complex.openai/videos__extensions__create/output.py +20 -0
  481. package/__fixtures__/-2.complex.openai/videos__list/input.json +477 -0
  482. package/__fixtures__/-2.complex.openai/videos__list/output.py +17 -0
  483. package/__fixtures__/-2.complex.openai/videos__remix/input.json +405 -0
  484. package/__fixtures__/-2.complex.openai/videos__remix/output.py +16 -0
  485. package/__fixtures__/-2.complex.openai/videos__retrieve/input.json +380 -0
  486. package/__fixtures__/-2.complex.openai/videos__retrieve/output.py +16 -0
  487. package/__fixtures__/1.basic/input.json +249 -0
  488. package/__fixtures__/1.basic/output/petstore/__init__.py +6 -0
  489. package/__fixtures__/1.basic/output/petstore/_client.py +21 -0
  490. package/__fixtures__/1.basic/output/petstore/_pagination.py +42 -0
  491. package/__fixtures__/1.basic/output/petstore/_transport.py +391 -0
  492. package/__fixtures__/1.basic/output/petstore/models.py +33 -0
  493. package/__fixtures__/1.basic/output/petstore/resources.py +25 -0
  494. package/__fixtures__/1.basic/output/pyproject.toml +12 -0
  495. package/__fixtures__/1.basic/output/tests/conftest.py +16 -0
  496. package/__fixtures__/1.basic/output/tests/test_pets.py +36 -0
  497. package/__fixtures__/1.basic/output/tests/utils.py +28 -0
  498. package/__fixtures__/2.wire/input.json +351 -0
  499. package/__fixtures__/2.wire/output/pyproject.toml +12 -0
  500. package/__fixtures__/2.wire/output/tests/conftest.py +16 -0
  501. package/__fixtures__/2.wire/output/tests/test_items.py +18 -0
  502. package/__fixtures__/2.wire/output/tests/test_tokens.py +17 -0
  503. package/__fixtures__/2.wire/output/tests/test_uploads.py +27 -0
  504. package/__fixtures__/2.wire/output/tests/utils.py +28 -0
  505. package/__fixtures__/2.wire/output/wire_service/__init__.py +6 -0
  506. package/__fixtures__/2.wire/output/wire_service/_client.py +23 -0
  507. package/__fixtures__/2.wire/output/wire_service/_pagination.py +42 -0
  508. package/__fixtures__/2.wire/output/wire_service/_transport.py +391 -0
  509. package/__fixtures__/2.wire/output/wire_service/models.py +44 -0
  510. package/__fixtures__/2.wire/output/wire_service/resources.py +38 -0
  511. package/__tests__/docs.test.ts +115 -0
  512. package/__tests__/e2e/harness.ts +79 -0
  513. package/__tests__/e2e/openai.test.ts +14 -0
  514. package/__tests__/e2e/publish.test.ts +19 -0
  515. package/__tests__/opensdk-python.test.ts +134 -0
  516. package/__tests__/utils.ts +117 -0
  517. package/biome.json +25 -0
  518. package/dist/index.cjs +1274 -0
  519. package/dist/index.cjs.map +1 -0
  520. package/dist/index.d.cts +32 -0
  521. package/dist/index.d.ts +32 -0
  522. package/dist/index.js +1246 -0
  523. package/dist/index.js.map +1 -0
  524. package/index.ts +1 -0
  525. package/package.json +30 -0
  526. package/src/emitter.ts +95 -0
  527. package/src/example-py.ts +60 -0
  528. package/src/index.ts +4 -0
  529. package/src/method.ts +13 -0
  530. package/src/naming.ts +45 -0
  531. package/src/project.ts +446 -0
  532. package/src/publish.ts +22 -0
  533. package/src/pytype.ts +86 -0
  534. package/src/runtime.ts +551 -0
  535. package/src/tests-py.ts +197 -0
  536. package/src/types.ts +8 -0
  537. package/tsconfig.json +18 -0
  538. package/tsup.config.ts +19 -0
  539. package/vitest.config.ts +8 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,1274 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ opensdkPython: () => opensdkPython,
24
+ publishPython: () => publishPython,
25
+ pythonEmitter: () => pythonEmitter,
26
+ writeProject: () => import_opensdk_framework5.writeProject
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/emitter.ts
31
+ var import_opensdk_core3 = require("@xyd-js/opensdk-core");
32
+ var import_opensdk_framework3 = require("@xyd-js/opensdk-framework");
33
+
34
+ // src/method.ts
35
+ function pyPageName(plan) {
36
+ return plan.pageName === "CursorPage" || plan.pageName === "Page" ? plan.pageName : null;
37
+ }
38
+
39
+ // src/naming.ts
40
+ function splitWords(input) {
41
+ return input.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).map((w) => w.trim().toLowerCase()).filter(Boolean);
42
+ }
43
+ function safeIdent(s) {
44
+ return /^[0-9]/.test(s) ? `_${s}` : s;
45
+ }
46
+ function pascalCase(input) {
47
+ const s = splitWords(input).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
48
+ return safeIdent(s);
49
+ }
50
+ function snakeCase(input) {
51
+ const s = safeIdent(splitWords(input).join("_"));
52
+ return PY_KEYWORDS.has(s) ? `${s}_` : s;
53
+ }
54
+ function pyModuleName(input) {
55
+ const s = splitWords(input).join("_").replace(/[^a-z0-9_]/g, "");
56
+ return s || "client";
57
+ }
58
+ function screamingSnakeCase(input) {
59
+ return safeIdent(splitWords(input).join("_").toUpperCase().replace(/[^A-Z0-9_]/g, ""));
60
+ }
61
+ var PY_KEYWORDS = /* @__PURE__ */ new Set([
62
+ "and",
63
+ "as",
64
+ "assert",
65
+ "async",
66
+ "await",
67
+ "break",
68
+ "class",
69
+ "continue",
70
+ "def",
71
+ "del",
72
+ "elif",
73
+ "else",
74
+ "except",
75
+ "finally",
76
+ "for",
77
+ "from",
78
+ "global",
79
+ "if",
80
+ "import",
81
+ "in",
82
+ "is",
83
+ "lambda",
84
+ "none",
85
+ "nonlocal",
86
+ "not",
87
+ "or",
88
+ "pass",
89
+ "raise",
90
+ "return",
91
+ "try",
92
+ "while",
93
+ "with",
94
+ "yield"
95
+ ]);
96
+
97
+ // src/project.ts
98
+ var import_opensdk_core = require("@xyd-js/opensdk-core");
99
+ var import_opensdk_framework = require("@xyd-js/opensdk-framework");
100
+
101
+ // src/pytype.ts
102
+ var PyUses = class {
103
+ constructor() {
104
+ this.typing = /* @__PURE__ */ new Set();
105
+ }
106
+ use(name) {
107
+ this.typing.add(name);
108
+ }
109
+ /** The `from typing import ...` line, or null when nothing is used. */
110
+ typingImport() {
111
+ if (this.typing.size === 0) return null;
112
+ const order = ["Any", "BinaryIO", "Optional", "Union"];
113
+ return `from typing import ${order.filter((n) => this.typing.has(n)).join(", ")}`;
114
+ }
115
+ };
116
+ function pyType(ref, uses) {
117
+ if (!ref) return anyType(uses);
118
+ const base = pyBase(ref, uses);
119
+ return ref.nullable ? optionalize(base, uses) : base;
120
+ }
121
+ function pyBase(ref, uses) {
122
+ switch (ref.kind) {
123
+ case "scalar":
124
+ return pyScalar(ref.scalar, ref.format, uses);
125
+ case "ref":
126
+ return ref.name ? pascalCase(ref.name) : anyType(uses);
127
+ case "array":
128
+ return `list[${pyType(ref.items, uses)}]`;
129
+ case "map":
130
+ return `dict[str, ${pyType(ref.values, uses)}]`;
131
+ default:
132
+ return anyType(uses);
133
+ }
134
+ }
135
+ function pyScalar(scalar, format, uses) {
136
+ switch (scalar) {
137
+ case "string":
138
+ if (format === "binary") {
139
+ uses.use("Union");
140
+ uses.use("BinaryIO");
141
+ return "Union[bytes, BinaryIO]";
142
+ }
143
+ return "str";
144
+ case "integer":
145
+ return "int";
146
+ case "number":
147
+ return "float";
148
+ case "boolean":
149
+ return "bool";
150
+ default:
151
+ return anyType(uses);
152
+ }
153
+ }
154
+ function anyType(uses) {
155
+ uses.use("Any");
156
+ return "Any";
157
+ }
158
+ function optionalize(type, uses) {
159
+ if (type.startsWith("Optional[")) return type;
160
+ uses.use("Optional");
161
+ return `Optional[${type}]`;
162
+ }
163
+ function isPassthroughType(type) {
164
+ return type === "Any" || type === "str" || type === "int" || type === "float" || type === "bool";
165
+ }
166
+
167
+ // src/project.ts
168
+ function resolvePythonOptions(spec, options) {
169
+ var _a, _b, _c;
170
+ const pkg = options.packageName ?? pyModuleName(spec.info.title);
171
+ return {
172
+ pkg,
173
+ baseURL: options.baseURL ?? ((_a = spec.servers) == null ? void 0 : _a[0]) ?? "",
174
+ envVar: ((_c = (_b = spec.security) == null ? void 0 : _b.find((s) => s.envVar)) == null ? void 0 : _c.envVar) ?? `${screamingSnakeCase(pkg)}_API_KEY`
175
+ };
176
+ }
177
+ function pyproject(pkg, spec) {
178
+ var _a, _b;
179
+ const info = spec.info;
180
+ const lines = [
181
+ "[build-system]",
182
+ 'requires = ["setuptools>=61"]',
183
+ 'build-backend = "setuptools.build_meta"',
184
+ "",
185
+ "[project]",
186
+ `name = ${JSON.stringify(pkg.replace(/_/g, "-"))}`,
187
+ `version = ${JSON.stringify(info.version || "0.0.0")}`
188
+ ];
189
+ if (info.description) lines.push(`description = ${JSON.stringify(info.description)}`);
190
+ lines.push('requires-python = ">=3.9"');
191
+ if ((_a = info.contact) == null ? void 0 : _a.name) lines.push(`authors = [{ name = ${JSON.stringify(info.contact.name)} }]`);
192
+ if ((_b = info.license) == null ? void 0 : _b.identifier) lines.push(`license = { text = ${JSON.stringify(info.license.identifier)} }`);
193
+ const urls = [];
194
+ if (info.homepage) urls.push(`Homepage = ${JSON.stringify(info.homepage)}`);
195
+ if (info.repository) urls.push(`Repository = ${JSON.stringify(info.repository)}`);
196
+ if (urls.length) lines.push("", "[project.urls]", ...urls);
197
+ lines.push("", "[tool.setuptools.packages.find]", `include = [${JSON.stringify(pkg)}]`);
198
+ return `${lines.join("\n")}
199
+ `;
200
+ }
201
+ function modelsPy(spec) {
202
+ const ctx = { uses: new PyUses(), needsField: false };
203
+ const types = spec.types || [];
204
+ const aliasKinds = /* @__PURE__ */ new Set(["alias", "union"]);
205
+ const structsEnums = types.filter((t) => !aliasKinds.has(t.kind));
206
+ const aliases = orderAliases(types.filter((t) => aliasKinds.has(t.kind)));
207
+ const decls = [...structsEnums, ...aliases].map((t) => namedType(t, ctx)).filter(Boolean);
208
+ const lines = [
209
+ "from __future__ import annotations",
210
+ "",
211
+ `from dataclasses import dataclass${ctx.needsField ? ", field" : ""}`,
212
+ "from enum import Enum"
213
+ ];
214
+ const typingLine = ctx.uses.typingImport();
215
+ if (typingLine) lines.push(typingLine);
216
+ return `${lines.join("\n")}
217
+
218
+
219
+ ${decls.join("\n\n\n")}
220
+ `;
221
+ }
222
+ function typeRefNames(ref, out) {
223
+ if (!ref) return;
224
+ if (ref.kind === "ref" && ref.name) out.add(ref.name);
225
+ typeRefNames(ref.items, out);
226
+ typeRefNames(ref.values, out);
227
+ }
228
+ function orderAliases(aliases) {
229
+ const byName = new Map(aliases.map((a) => [a.name, a]));
230
+ const ordered = [];
231
+ const done = /* @__PURE__ */ new Set();
232
+ const visiting = /* @__PURE__ */ new Set();
233
+ const visit = (a) => {
234
+ if (done.has(a.name) || visiting.has(a.name)) return;
235
+ visiting.add(a.name);
236
+ const refs = /* @__PURE__ */ new Set();
237
+ if (a.kind === "alias") typeRefNames(a.of, refs);
238
+ for (const r of refs) {
239
+ const dep = byName.get(r);
240
+ if (dep && dep !== a) visit(dep);
241
+ }
242
+ visiting.delete(a.name);
243
+ done.add(a.name);
244
+ ordered.push(a);
245
+ };
246
+ for (const a of aliases) visit(a);
247
+ return ordered;
248
+ }
249
+ function namedType(type, ctx) {
250
+ switch (type.kind) {
251
+ case "enum":
252
+ return enumType(type);
253
+ case "alias":
254
+ return `${pascalCase(type.name)} = ${pyType(type.of, ctx.uses)}`;
255
+ case "union":
256
+ ctx.uses.use("Any");
257
+ return `${pascalCase(type.name)} = Any`;
258
+ default:
259
+ return structType(type, ctx);
260
+ }
261
+ }
262
+ function structType(type, ctx) {
263
+ const name = pascalCase(type.name);
264
+ const fields = type.fields || [];
265
+ if (fields.length === 0) return `@dataclass
266
+ class ${name}:
267
+ pass`;
268
+ const required = fields.filter((f) => f.required);
269
+ const optional = fields.filter((f) => !f.required);
270
+ const lines = [...required, ...optional].map((f) => structFieldLine(f, ctx));
271
+ return `@dataclass
272
+ class ${name}:
273
+ ${lines.join("\n")}`;
274
+ }
275
+ function structFieldLine(f, ctx) {
276
+ const py = snakeCase(f.name);
277
+ const type = pyType(f.type, ctx.uses);
278
+ const wire = py === f.name ? null : `metadata={"wire": ${JSON.stringify(f.name)}}`;
279
+ if (f.required) {
280
+ if (!wire) return ` ${py}: ${type}`;
281
+ ctx.needsField = true;
282
+ return ` ${py}: ${type} = field(${wire})`;
283
+ }
284
+ const opt = optionalize(type, ctx.uses);
285
+ if (!wire) return ` ${py}: ${opt} = None`;
286
+ ctx.needsField = true;
287
+ return ` ${py}: ${opt} = field(default=None, ${wire})`;
288
+ }
289
+ function enumType(type) {
290
+ const name = pascalCase(type.name);
291
+ const base = type.base === "integer" ? "int" : "str";
292
+ const values = type.values || [];
293
+ if (values.length === 0) return `class ${name}(${base}, Enum):
294
+ pass`;
295
+ const members = values.map((v) => {
296
+ const member = screamingSnakeCase(String(v.name ?? v.value)) || "VALUE";
297
+ const lit = base === "int" ? String(v.value) : JSON.stringify(String(v.value));
298
+ return ` ${member} = ${lit}`;
299
+ });
300
+ return `class ${name}(${base}, Enum):
301
+ ${members.join("\n")}`;
302
+ }
303
+ function resourcesPy(spec, types) {
304
+ const ctx = {
305
+ types,
306
+ behavior: (0, import_opensdk_core.sdkBehavior)(spec),
307
+ uses: new PyUses(),
308
+ transportImports: /* @__PURE__ */ new Set(),
309
+ pages: /* @__PURE__ */ new Set()
310
+ };
311
+ const classes = [];
312
+ const emit = (resources, parent) => {
313
+ var _a;
314
+ for (const r of resources) {
315
+ const segments = [...parent, r.name];
316
+ classes.push(resourceClass(r, segments, ctx));
317
+ if ((_a = r.resources) == null ? void 0 : _a.length) emit(r.resources, segments);
318
+ }
319
+ };
320
+ emit(spec.resources || [], []);
321
+ const lines = ["from __future__ import annotations", ""];
322
+ const typingLine = ctx.uses.typingImport();
323
+ if (typingLine) lines.push(typingLine, "");
324
+ if (ctx.pages.size > 0) {
325
+ const pageNames = ["CursorPage", "Page"].filter((n) => ctx.pages.has(n));
326
+ lines.push(`from ._pagination import ${pageNames.join(", ")}`);
327
+ }
328
+ const transportNames = ["Transport", ...["decode", "join_csv"].filter((n) => ctx.transportImports.has(n))];
329
+ lines.push(`from ._transport import ${transportNames.join(", ")}`);
330
+ lines.push("from .models import * # noqa: F401,F403");
331
+ return `${lines.join("\n")}
332
+
333
+
334
+ ${classes.join("\n\n\n")}
335
+ `;
336
+ }
337
+ function resourceClassName(segments) {
338
+ return `${segments.map((s) => pascalCase(s)).join("")}Resource`;
339
+ }
340
+ function resourceClass(resource, segments, ctx) {
341
+ const cls = resourceClassName(segments);
342
+ const subs = resource.resources || [];
343
+ const ctorLines = [" self._transport = transport"];
344
+ for (const sub of subs)
345
+ ctorLines.push(` self.${snakeCase(sub.name)} = ${resourceClassName([...segments, sub.name])}(transport)`);
346
+ const ctor = ` def __init__(self, transport: Transport) -> None:
347
+ ${ctorLines.join("\n")}`;
348
+ const methods = (resource.methods || []).map((m) => methodDef(m, ctx));
349
+ return `class ${cls}:
350
+ ${[ctor, ...methods].join("\n\n")}`;
351
+ }
352
+ function methodDef(method, ctx) {
353
+ const plan = (0, import_opensdk_framework.planOperation)(method, ctx.types);
354
+ const name = snakeCase(method.action);
355
+ const { path: pathParams, query: queryParams, header: headerParams } = plan.paramGroups;
356
+ const rawContentType = plan.binaryContentType;
357
+ const positional = pathParams.map((p) => `${snakeCase(p.name)}: ${pyType(p.type, ctx.uses)}`);
358
+ const kwArgs = [];
359
+ for (const p of [...queryParams, ...headerParams]) kwArgs.push(paramArg(p, ctx));
360
+ const bodyParams = bodyFieldList(method, ctx.types);
361
+ for (const b of bodyParams) {
362
+ const type = pyType(b.type, ctx.uses);
363
+ kwArgs.push(
364
+ b.required ? `${snakeCase(b.name)}: ${type}` : `${snakeCase(b.name)}: ${optionalize(type, ctx.uses)} = None`
365
+ );
366
+ }
367
+ const params = ["self", ...positional, ...kwArgs.length ? ["*", ...kwArgs] : []].join(", ");
368
+ const httpMethod = method.httpMethod.toUpperCase();
369
+ const callArgs = [JSON.stringify(httpMethod), pathExpr(method.path, pathParams.length > 0)];
370
+ if (queryParams.length) {
371
+ callArgs.push(`query={${queryParams.map((q) => queryEntry(q, ctx)).join(", ")}}`);
372
+ }
373
+ if (bodyParams.length) {
374
+ const entries = bodyParams.map((b) => `${JSON.stringify(b.name)}: ${snakeCase(b.name)}`).join(", ");
375
+ callArgs.push(`body={${entries}}`);
376
+ }
377
+ const headerEntries = headerParams.map((h) => `${JSON.stringify(h.wireName ?? h.name)}: ${snakeCase(h.name)}`);
378
+ if (rawContentType) headerEntries.unshift(`"Accept": ${JSON.stringify(rawContentType)}`);
379
+ if (headerEntries.length) callArgs.push(`headers={${headerEntries.join(", ")}}`);
380
+ let encoding = plan.encoding ?? "json";
381
+ if (bodyParams.length && encoding === "json" && bodyParams.some((b) => isBinaryTypeRef(b.type, ctx.types))) {
382
+ encoding = "multipart";
383
+ }
384
+ if (bodyParams.length && encoding !== "json") callArgs.push(`encoding=${JSON.stringify(encoding)}`);
385
+ if (rawContentType) callArgs.push("raw=True");
386
+ if (plan.injectIdempotencyKey && ctx.behavior.idempotency.autoGenerateForPost) {
387
+ callArgs.push("idempotency=True");
388
+ }
389
+ const call = `self._transport.request(${callArgs.join(", ")})`;
390
+ const { annotation, body } = returnPlan(plan, call, ctx);
391
+ const guards = pathParamGuards(pathParams);
392
+ const fullBody = guards ? `${guards}
393
+ ${body}` : body;
394
+ return ` def ${name}(${params}) -> ${annotation}:
395
+ ${fullBody}`;
396
+ }
397
+ function pathParamGuards(pathParams) {
398
+ var _a;
399
+ const lines = [];
400
+ for (const p of pathParams) {
401
+ if (((_a = p.type) == null ? void 0 : _a.kind) !== "scalar" || p.type.scalar !== "string" || p.required === false) continue;
402
+ const n = snakeCase(p.name);
403
+ lines.push(` if not ${n}:`);
404
+ lines.push(` raise ValueError(f"Expected a non-empty value for \`${n}\` but received {${n}!r}")`);
405
+ }
406
+ return lines.join("\n");
407
+ }
408
+ function paramArg(p, ctx) {
409
+ const type = pyType(p.type, ctx.uses);
410
+ if (p.required) return `${snakeCase(p.name)}: ${type}`;
411
+ return `${snakeCase(p.name)}: ${optionalize(type, ctx.uses)} = None`;
412
+ }
413
+ function queryEntry(q, ctx) {
414
+ var _a;
415
+ const wire = JSON.stringify(q.wireName ?? q.name);
416
+ const value = snakeCase(q.name);
417
+ if (((_a = q.type) == null ? void 0 : _a.kind) === "array" && q.explode === false) {
418
+ ctx.transportImports.add("join_csv");
419
+ return `${wire}: join_csv(${value})`;
420
+ }
421
+ return `${wire}: ${value}`;
422
+ }
423
+ function returnPlan(plan, call, ctx) {
424
+ var _a;
425
+ const { method } = plan;
426
+ if (plan.binaryContentType) return { annotation: "bytes", body: ` return ${call}` };
427
+ const page = pyPageName(plan);
428
+ if (page) {
429
+ ctx.pages.add(page);
430
+ const item = pyType((_a = method.pagination) == null ? void 0 : _a.itemType, ctx.uses);
431
+ return { annotation: `${page}[${item}]`, body: ` return ${page}.from_response(${item}, ${call})` };
432
+ }
433
+ const primary = method.primaryResponse;
434
+ if (!primary) return { annotation: "None", body: ` ${call}` };
435
+ const type = pyType(primary, ctx.uses);
436
+ if (isPassthroughType(type)) return { annotation: type, body: ` return ${call}` };
437
+ ctx.transportImports.add("decode");
438
+ return { annotation: type, body: ` return decode(${type}, ${call})` };
439
+ }
440
+ function isBinaryTypeRef(ref, types, seen = /* @__PURE__ */ new Set()) {
441
+ if (!ref) return false;
442
+ if (ref.kind === "scalar") return ref.scalar === "string" && ref.format === "binary";
443
+ if (ref.kind === "array") return isBinaryTypeRef(ref.items, types, seen);
444
+ if (ref.kind === "ref" && ref.name) {
445
+ if (seen.has(ref.name)) return false;
446
+ seen.add(ref.name);
447
+ const named = types.get(ref.name);
448
+ if (!named) return false;
449
+ if (named.kind === "union") {
450
+ return (named.variants || []).some((v) => isBinaryTypeRef(v, types, seen));
451
+ }
452
+ if (named.kind === "alias") return isBinaryTypeRef(named.of, types, seen);
453
+ }
454
+ return false;
455
+ }
456
+ function bodyFieldList(method, types) {
457
+ var _a;
458
+ const ref = (_a = method.requestBody) == null ? void 0 : _a.type;
459
+ if ((ref == null ? void 0 : ref.kind) !== "ref" || !ref.name) return [];
460
+ const named = types.get(ref.name);
461
+ return ((named == null ? void 0 : named.fields) || []).map((f) => ({ name: f.name, type: f.type, required: f.required === true }));
462
+ }
463
+ function pathExpr(path, hasParams) {
464
+ const p = path.startsWith("/") ? path : `/${path}`;
465
+ if (!hasParams) return JSON.stringify(p);
466
+ const fstr = p.replace(/\{([^}]+)\}/g, (_, name) => `{${snakeCase(name)}}`);
467
+ return `f${JSON.stringify(fstr)}`;
468
+ }
469
+ function clientPy(spec, envVar) {
470
+ const resources = spec.resources || [];
471
+ const attrLines = resources.map(
472
+ (r) => ` self.${snakeCase(r.name)} = ${resourceClassName([r.name])}(self._transport)`
473
+ );
474
+ const imports = resources.map((r) => resourceClassName([r.name])).join(", ");
475
+ return `from __future__ import annotations
476
+
477
+ import os
478
+ from typing import Optional
479
+
480
+ from ._transport import Transport
481
+ from .resources import ${imports}
482
+
483
+
484
+ class Client:
485
+ def __init__(
486
+ self,
487
+ api_key: Optional[str] = None,
488
+ base_url: Optional[str] = None,
489
+ timeout: Optional[float] = None,
490
+ ) -> None:
491
+ key = api_key if api_key is not None else os.environ.get(${JSON.stringify(envVar)})
492
+ self._transport = Transport(base_url=base_url, api_key=key, timeout=timeout)
493
+ ${attrLines.join("\n")}
494
+ `;
495
+ }
496
+
497
+ // src/runtime.ts
498
+ var import_opensdk_core2 = require("@xyd-js/opensdk-core");
499
+ function pyStr(value) {
500
+ return JSON.stringify(value);
501
+ }
502
+ function pyBool(value) {
503
+ return value ? "True" : "False";
504
+ }
505
+ function pyFloat(value) {
506
+ return Number.isInteger(value) ? `${value}.0` : String(value);
507
+ }
508
+ function pyFrozenset(items) {
509
+ return items.length ? `frozenset({${items.join(", ")}})` : "frozenset()";
510
+ }
511
+ function pyStrDict(record) {
512
+ const entries = Object.entries(record).map(([key, value]) => `${pyStr(key)}: ${pyStr(value)}`);
513
+ return `{${entries.join(", ")}}`;
514
+ }
515
+ function errorClassName(kind) {
516
+ if (kind === "API") return "APIError";
517
+ return kind.endsWith("Error") ? kind : `${kind}Error`;
518
+ }
519
+ function errorClassNames(spec) {
520
+ const behavior = (0, import_opensdk_core2.sdkBehavior)(spec);
521
+ const names = /* @__PURE__ */ new Set();
522
+ for (const kind of Object.values(behavior.errors.statusCodeMap)) names.add(errorClassName(kind));
523
+ names.add(errorClassName(behavior.errors.serverErrorKind));
524
+ names.add(errorClassName(behavior.errors.clientErrorKind));
525
+ names.delete("APIError");
526
+ return [...names].sort();
527
+ }
528
+ function errorClassesBlock(behavior) {
529
+ const mapped = Object.entries(behavior.errors.statusCodeMap).map(([status, kind]) => [Number(status), kind]).sort((a, b) => a[0] - b[0]);
530
+ const byClass = /* @__PURE__ */ new Map();
531
+ for (const [status, kind] of mapped) {
532
+ const cls = errorClassName(kind);
533
+ if (cls === "APIError") continue;
534
+ const entry = byClass.get(cls) || { kind, statuses: [] };
535
+ entry.statuses.push(status);
536
+ byClass.set(cls, entry);
537
+ }
538
+ const serverClass = errorClassName(behavior.errors.serverErrorKind);
539
+ const clientClass = errorClassName(behavior.errors.clientErrorKind);
540
+ const errorClass = (cls, kind, doc) => `class ${cls}(APIError):
541
+ """${doc}"""
542
+
543
+ kind = ${pyStr(kind)}`;
544
+ const classes = [];
545
+ for (const [cls, { kind, statuses }] of byClass) {
546
+ classes.push(errorClass(cls, kind, `The mapped error kind for HTTP ${statuses.join("/")} responses.`));
547
+ }
548
+ if (serverClass !== "APIError" && !byClass.has(serverClass)) {
549
+ classes.push(errorClass(serverClass, behavior.errors.serverErrorKind, "Catch-all for unmapped 5xx responses."));
550
+ }
551
+ if (clientClass !== "APIError" && !byClass.has(clientClass) && clientClass !== serverClass) {
552
+ classes.push(
553
+ errorClass(clientClass, behavior.errors.clientErrorKind, "Catch-all for unmapped non-5xx error responses.")
554
+ );
555
+ }
556
+ const tableEntries = mapped.map(([status, kind]) => ` ${status}: ${errorClassName(kind)},`);
557
+ const table = tableEntries.length ? `_STATUS_TO_ERROR: dict[int, type] = {
558
+ ${tableEntries.join("\n")}
559
+ }` : "_STATUS_TO_ERROR: dict[int, type] = {}";
560
+ return `${classes.join("\n\n\n")}
561
+
562
+
563
+ ${table}
564
+
565
+
566
+ def _error_for_status(status_code: int, headers: dict[str, str], body: bytes) -> APIError:
567
+ """The policy-mapped exception: exact status map first, then the 5xx catch-all, then the client catch-all."""
568
+ cls = _STATUS_TO_ERROR.get(status_code)
569
+ if cls is None:
570
+ cls = ${serverClass} if status_code >= 500 else ${clientClass}
571
+ return cls(status_code, headers, body)`;
572
+ }
573
+ function transportPy(spec, pkg, baseURL) {
574
+ var _a;
575
+ const behavior = (0, import_opensdk_core2.sdkBehavior)(spec);
576
+ const security = (_a = spec.security) == null ? void 0 : _a[0];
577
+ let authLine = "";
578
+ if (security) {
579
+ const name = security.name || "";
580
+ switch (security.kind) {
581
+ case "apiKey-header":
582
+ authLine = ` request_headers[${JSON.stringify(name)}] = self.api_key
583
+ `;
584
+ break;
585
+ case "apiKey-query":
586
+ authLine = ` params[${JSON.stringify(name)}] = self.api_key
587
+ `;
588
+ break;
589
+ default:
590
+ authLine = ` request_headers["Authorization"] = "Bearer " + self.api_key
591
+ `;
592
+ }
593
+ }
594
+ const authBlock = authLine ? ` if self.api_key:
595
+ ${authLine}` : "";
596
+ const userAgent = behavior.userAgent.sdkIdentifierTemplate.replace(/\{package\}/g, pkg).replace(/\{language\}/g, "python").replace(/\{version\}/g, spec.info.version || "0.0.0");
597
+ const timeoutMs = behavior.timeout.defaultTimeoutMs;
598
+ const defaultTimeout = timeoutMs > 0 ? pyFloat(timeoutMs / 1e3) : "None";
599
+ const timeoutEnvVar = behavior.timeout.timeoutEnvVar;
600
+ const retry = behavior.retry;
601
+ const errorDocUrlTemplate = behavior.errors.errorDocUrlTemplate;
602
+ const includeRuntimeVersion = behavior.userAgent.includeRuntimeVersion;
603
+ const constants = [
604
+ `DEFAULT_BASE_URL = ${pyStr(baseURL)}`,
605
+ `USER_AGENT = ${pyStr(userAgent)}`,
606
+ `AI_AGENT_ENV_VARS = ${pyStrDict(behavior.userAgent.aiAgentEnvVars)}`,
607
+ `DEFAULT_TIMEOUT: Optional[float] = ${defaultTimeout}`,
608
+ ...timeoutEnvVar ? [`TIMEOUT_ENV_VAR = ${pyStr(timeoutEnvVar)}`] : [],
609
+ `MAX_RETRIES = ${retry.maxRetries}`,
610
+ `RETRYABLE_STATUS_CODES = ${pyFrozenset(retry.retryableStatusCodes.map(String))}`,
611
+ `RETRY_CONNECTION_ERRORS = ${pyBool(retry.retryConnectionErrors)}`,
612
+ `HONOR_RETRY_AFTER_HEADER = ${pyBool(retry.honorRetryAfterHeader)}`,
613
+ `BACKOFF_INITIAL_DELAY = ${pyFloat(retry.backoff.initialDelayMs / 1e3)}`,
614
+ `BACKOFF_MAX_DELAY = ${pyFloat(retry.backoff.maxDelayMs / 1e3)}`,
615
+ `BACKOFF_MULTIPLIER = ${pyFloat(retry.backoff.multiplier)}`,
616
+ `BACKOFF_JITTER = ${pyFloat(retry.backoff.jitter)}`,
617
+ `REQUEST_ID_HEADER = ${pyStr(behavior.telemetry.requestIdHeader)}`,
618
+ `IDEMPOTENCY_HEADER = ${pyStr(behavior.idempotency.headerName)}`,
619
+ ...errorDocUrlTemplate ? [`ERROR_DOC_URL_TEMPLATE = ${pyStr(errorDocUrlTemplate)}`] : [],
620
+ `GUARDED_OPTION_KEYS = ${pyFrozenset(behavior.requestGuard.optionKeys.map(pyStr))}`
621
+ ].join("\n");
622
+ const errorDocStr = errorDocUrlTemplate ? `
623
+
624
+ def __str__(self) -> str:
625
+ url = ERROR_DOC_URL_TEMPLATE.replace("{kind}", self.kind).replace("{status}", str(self.status_code))
626
+ return self.message + " (" + url + ")"` : "";
627
+ const runtimeVersionLine = includeRuntimeVersion ? '\n ua += " python/" + platform.python_version()' : "";
628
+ return `from __future__ import annotations
629
+
630
+ import dataclasses
631
+ import datetime
632
+ import email.utils
633
+ import json
634
+ import os${includeRuntimeVersion ? "\nimport platform" : ""}
635
+ import random
636
+ import time
637
+ import typing
638
+ import urllib.error
639
+ import urllib.parse
640
+ import urllib.request
641
+ import uuid
642
+ from enum import Enum
643
+ from typing import Any, Optional
644
+
645
+ ${constants}
646
+
647
+
648
+ class APIError(Exception):
649
+ """A non-2xx API response: status code, headers, raw body, request id and a best-effort message."""
650
+
651
+ kind = "API"
652
+
653
+ def __init__(self, status_code: int, headers: dict[str, str], body: bytes) -> None:
654
+ self.status_code = status_code
655
+ self.headers = headers
656
+ self.body = body
657
+ self.request_id = _header(headers, REQUEST_ID_HEADER)
658
+ self.message = _error_message(body) or "HTTP " + str(status_code)
659
+ super().__init__(self.message)${errorDocStr}
660
+
661
+
662
+ ${errorClassesBlock(behavior)}
663
+
664
+
665
+ def _error_message(body: bytes) -> Optional[str]:
666
+ """Best-effort message from a JSON error envelope ({"error": {"message": ...}} etc.)."""
667
+ try:
668
+ payload = json.loads(body.decode("utf-8"))
669
+ except Exception:
670
+ return None
671
+ if not isinstance(payload, dict):
672
+ return None
673
+ error = payload.get("error")
674
+ if isinstance(error, dict) and isinstance(error.get("message"), str):
675
+ return error["message"]
676
+ if isinstance(error, str):
677
+ return error
678
+ for key in ("message", "detail"):
679
+ if isinstance(payload.get(key), str):
680
+ return payload[key]
681
+ return None
682
+
683
+
684
+ def _header(headers: dict[str, str], name: str) -> Optional[str]:
685
+ """Case-insensitive header lookup."""
686
+ target = name.lower()
687
+ for key, value in headers.items():
688
+ if key.lower() == target:
689
+ return value
690
+ return None
691
+
692
+
693
+ def _user_agent() -> str:
694
+ """The policy User-Agent: SDK identifier, plus an AI-agent slug when a known agent env var is set."""
695
+ ua = USER_AGENT${runtimeVersionLine}
696
+ for env_var, slug in AI_AGENT_ENV_VARS.items():
697
+ if os.environ.get(env_var):
698
+ ua += " agent/" + slug
699
+ break
700
+ return ua
701
+
702
+
703
+ def _default_timeout() -> Optional[float]:
704
+ ${timeoutEnvVar ? ` """The policy default timeout in seconds; TIMEOUT_ENV_VAR (milliseconds) overrides it when set."""
705
+ raw = os.environ.get(TIMEOUT_ENV_VAR)
706
+ if raw:
707
+ try:
708
+ return float(raw) / 1000.0
709
+ except ValueError:
710
+ pass
711
+ return DEFAULT_TIMEOUT` : ` """The policy default timeout in seconds (None = no deadline)."""
712
+ return DEFAULT_TIMEOUT`}
713
+
714
+
715
+ def _retry_delay(attempt: int, headers: Optional[dict[str, str]]) -> float:
716
+ """Seconds to sleep before retry attempt (0-based): a Retry-After header
717
+ wins when honored; otherwise min(initial * multiplier**attempt, max) plus
718
+ proportional random jitter."""
719
+ if HONOR_RETRY_AFTER_HEADER and headers:
720
+ retry_after = _retry_after_seconds(headers)
721
+ if retry_after is not None:
722
+ return retry_after
723
+ delay = min(BACKOFF_INITIAL_DELAY * (BACKOFF_MULTIPLIER ** attempt), BACKOFF_MAX_DELAY)
724
+ return delay + delay * BACKOFF_JITTER * random.random()
725
+
726
+
727
+ def _retry_after_seconds(headers: dict[str, str]) -> Optional[float]:
728
+ """A Retry-After header as seconds: both the integer-seconds and the HTTP-date forms."""
729
+ value = _header(headers, "Retry-After")
730
+ if value is None:
731
+ return None
732
+ value = value.strip()
733
+ if value.isdigit():
734
+ return float(value)
735
+ try:
736
+ parsed = email.utils.parsedate_to_datetime(value)
737
+ except (TypeError, ValueError):
738
+ return None
739
+ if parsed is None:
740
+ return None
741
+ if parsed.tzinfo is None:
742
+ parsed = parsed.replace(tzinfo=datetime.timezone.utc)
743
+ return max(0.0, (parsed - datetime.datetime.now(datetime.timezone.utc)).total_seconds())
744
+
745
+
746
+ def _guard_options(params: Optional[dict[str, Any]]) -> None:
747
+ """Fail fast when a request-option key (api_key, max_retries, ...) is
748
+ misplaced into request params \u2014 a misplaced credential would otherwise be
749
+ sent on the wire and end up in provider logs."""
750
+ for key in params or ():
751
+ if key in GUARDED_OPTION_KEYS:
752
+ raise ValueError(
753
+ "request option " + repr(key) + " must be set on the client, not passed as a request parameter"
754
+ )
755
+
756
+
757
+ def encode(value: Any) -> Any:
758
+ """Wire-encode a request value: dataclasses -> dicts keyed by wire name
759
+ (None fields dropped), enums -> their values; lists/dicts recurse."""
760
+ if isinstance(value, Enum):
761
+ return encode(value.value)
762
+ if dataclasses.is_dataclass(value) and not isinstance(value, type):
763
+ out: dict[str, Any] = {}
764
+ for f in dataclasses.fields(value):
765
+ item = getattr(value, f.name)
766
+ if item is None:
767
+ continue
768
+ out[f.metadata.get("wire", f.name)] = encode(item)
769
+ return out
770
+ if isinstance(value, (list, tuple)):
771
+ return [encode(item) for item in value]
772
+ if isinstance(value, dict):
773
+ return {key: encode(item) for key, item in value.items()}
774
+ return value
775
+
776
+
777
+ def decode(tp: Any, value: Any) -> Any:
778
+ """Best-effort decode of parsed JSON into the generated models: dataclasses
779
+ are built field-by-field (honoring wire names), enums by value; unknown
780
+ shapes are returned as-is."""
781
+ if value is None or tp is None or tp is Any:
782
+ return value
783
+ origin = typing.get_origin(tp)
784
+ if origin is not None:
785
+ args = typing.get_args(tp)
786
+ if origin is list and isinstance(value, list):
787
+ item_tp = args[0] if args else Any
788
+ return [decode(item_tp, item) for item in value]
789
+ if origin is dict and isinstance(value, dict):
790
+ value_tp = args[1] if len(args) > 1 else Any
791
+ return {key: decode(value_tp, item) for key, item in value.items()}
792
+ if origin is typing.Union:
793
+ for arg in args:
794
+ if arg is type(None):
795
+ continue
796
+ try:
797
+ decoded = decode(arg, value)
798
+ except Exception:
799
+ continue
800
+ if decoded is not value:
801
+ return decoded
802
+ return value
803
+ return value
804
+ if isinstance(tp, type) and issubclass(tp, Enum):
805
+ try:
806
+ return tp(value)
807
+ except ValueError:
808
+ return value
809
+ if isinstance(tp, type) and dataclasses.is_dataclass(tp) and isinstance(value, dict):
810
+ try:
811
+ hints = typing.get_type_hints(tp)
812
+ except Exception:
813
+ hints = {}
814
+ kwargs: dict[str, Any] = {}
815
+ for f in dataclasses.fields(tp):
816
+ wire = f.metadata.get("wire", f.name)
817
+ if wire in value:
818
+ kwargs[f.name] = decode(hints.get(f.name, Any), value[wire])
819
+ elif f.default is dataclasses.MISSING and f.default_factory is dataclasses.MISSING:
820
+ kwargs[f.name] = None
821
+ return tp(**kwargs)
822
+ return value
823
+
824
+
825
+ def join_csv(value: Optional[list]) -> Optional[str]:
826
+ """Serialize an explode=false array parameter as one comma-joined value."""
827
+ if value is None:
828
+ return None
829
+ return ",".join(_text(encode(item)) for item in value)
830
+
831
+
832
+ def _text(value: Any) -> str:
833
+ if isinstance(value, bool):
834
+ return "true" if value else "false"
835
+ if isinstance(value, (dict, list)):
836
+ return json.dumps(value)
837
+ return str(value)
838
+
839
+
840
+ def _query_value(value: Any) -> Any:
841
+ encoded = encode(value)
842
+ if isinstance(encoded, list):
843
+ return [_text(item) for item in encoded]
844
+ return _text(encoded)
845
+
846
+
847
+ def _multipart(payload: dict[str, Any]) -> tuple[bytes, str]:
848
+ """Encode a multipart/form-data body (stdlib-only, manual boundary).
849
+ bytes / file-like values become file parts; lists become repeated parts."""
850
+ boundary = uuid.uuid4().hex
851
+ chunks: list[bytes] = []
852
+ for name, value in payload.items():
853
+ items = value if isinstance(value, list) else [value]
854
+ for item in items:
855
+ chunks.append(("--" + boundary + "\\r\\n").encode("utf-8"))
856
+ if isinstance(item, bytes) or hasattr(item, "read"):
857
+ content = item if isinstance(item, bytes) else item.read()
858
+ if isinstance(content, str):
859
+ content = content.encode("utf-8")
860
+ filename = str(getattr(item, "name", name)).replace("\\\\", "/").split("/")[-1] or name
861
+ disposition = 'Content-Disposition: form-data; name="' + name + '"; filename="' + filename + '"\\r\\n'
862
+ chunks.append(disposition.encode("utf-8"))
863
+ chunks.append(b"Content-Type: application/octet-stream\\r\\n\\r\\n")
864
+ chunks.append(content)
865
+ else:
866
+ chunks.append(('Content-Disposition: form-data; name="' + name + '"\\r\\n\\r\\n').encode("utf-8"))
867
+ chunks.append(_text(item).encode("utf-8"))
868
+ chunks.append(b"\\r\\n")
869
+ chunks.append(("--" + boundary + "--\\r\\n").encode("utf-8"))
870
+ return b"".join(chunks), "multipart/form-data; boundary=" + boundary
871
+
872
+
873
+ class Transport:
874
+ def __init__(
875
+ self,
876
+ base_url: Optional[str] = None,
877
+ api_key: Optional[str] = None,
878
+ timeout: Optional[float] = None,
879
+ ) -> None:
880
+ self.base_url = (base_url or DEFAULT_BASE_URL).rstrip("/")
881
+ self.api_key = api_key
882
+ self.timeout = timeout if timeout is not None else _default_timeout()
883
+ self.user_agent = _user_agent()
884
+
885
+ def request(
886
+ self,
887
+ method: str,
888
+ path: str,
889
+ query: Optional[dict[str, Any]] = None,
890
+ body: Optional[dict[str, Any]] = None,
891
+ headers: Optional[dict[str, Any]] = None,
892
+ encoding: str = "json",
893
+ raw: bool = False,
894
+ idempotency: bool = False,
895
+ ) -> Any:
896
+ _guard_options(query)
897
+ _guard_options(body)
898
+ url = self.base_url + path
899
+ params = {k: _query_value(v) for k, v in (query or {}).items() if v is not None}
900
+ request_headers: dict[str, str] = {k: _text(v) for k, v in (headers or {}).items() if v is not None}
901
+ request_headers.setdefault("User-Agent", self.user_agent)
902
+ data = None
903
+ if body is not None:
904
+ payload = {k: encode(v) for k, v in body.items() if v is not None}
905
+ if encoding == "multipart":
906
+ data, content_type = _multipart(payload)
907
+ request_headers["Content-Type"] = content_type
908
+ elif encoding == "form":
909
+ data = urllib.parse.urlencode(payload, doseq=True).encode("utf-8")
910
+ request_headers["Content-Type"] = "application/x-www-form-urlencoded"
911
+ else:
912
+ data = json.dumps(payload).encode("utf-8")
913
+ request_headers["Content-Type"] = "application/json"
914
+ ${authBlock} if idempotency:
915
+ # One key per logical call, generated before the retry loop so every
916
+ # retry of this request carries the SAME idempotency key.
917
+ request_headers.setdefault(IDEMPOTENCY_HEADER, str(uuid.uuid4()))
918
+ if params:
919
+ url += "?" + urllib.parse.urlencode(params, doseq=True)
920
+ attempt = 0
921
+ while True:
922
+ request = urllib.request.Request(url, data=data, method=method, headers=request_headers)
923
+ try:
924
+ with urllib.request.urlopen(request, timeout=self.timeout) as response:
925
+ content = response.read()
926
+ except urllib.error.HTTPError as error:
927
+ error_headers = dict(error.headers.items())
928
+ error_body = error.read()
929
+ if attempt < MAX_RETRIES and error.code in RETRYABLE_STATUS_CODES:
930
+ time.sleep(_retry_delay(attempt, error_headers))
931
+ attempt += 1
932
+ continue
933
+ raise _error_for_status(error.code, error_headers, error_body) from None
934
+ except OSError:
935
+ # Connection/timeout errors (URLError, reset, DNS failure, socket timeout).
936
+ if RETRY_CONNECTION_ERRORS and attempt < MAX_RETRIES:
937
+ time.sleep(_retry_delay(attempt, None))
938
+ attempt += 1
939
+ continue
940
+ raise
941
+ if raw:
942
+ return content
943
+ return json.loads(content.decode("utf-8")) if content else None
944
+ `;
945
+ }
946
+ function paginationPy() {
947
+ return `from __future__ import annotations
948
+
949
+ from dataclasses import dataclass, field
950
+ from typing import Any, Generic, Iterator, TypeVar
951
+
952
+ from ._transport import decode
953
+
954
+ T = TypeVar("T")
955
+
956
+
957
+ @dataclass
958
+ class CursorPage(Generic[T]):
959
+ """One page of a cursor-paginated list: \`data\` plus a \`has_more\` marker."""
960
+
961
+ data: list[T] = field(default_factory=list)
962
+ has_more: bool = False
963
+
964
+ def __iter__(self) -> Iterator[T]:
965
+ return iter(self.data)
966
+
967
+ @classmethod
968
+ def from_response(cls, item_type: Any, raw: Any) -> CursorPage[T]:
969
+ payload = raw if isinstance(raw, dict) else {}
970
+ data = [decode(item_type, item) for item in payload.get("data") or []]
971
+ return cls(data=data, has_more=bool(payload.get("has_more") or False))
972
+
973
+
974
+ @dataclass
975
+ class Page(Generic[T]):
976
+ """One page of a marker-less list: the whole collection in one \`data\` envelope."""
977
+
978
+ data: list[T] = field(default_factory=list)
979
+
980
+ def __iter__(self) -> Iterator[T]:
981
+ return iter(self.data)
982
+
983
+ @classmethod
984
+ def from_response(cls, item_type: Any, raw: Any) -> Page[T]:
985
+ payload = raw if isinstance(raw, dict) else {}
986
+ return cls(data=[decode(item_type, item) for item in payload.get("data") or []])
987
+ `;
988
+ }
989
+
990
+ // src/tests-py.ts
991
+ var import_opensdk_framework2 = require("@xyd-js/opensdk-framework");
992
+
993
+ // src/example-py.ts
994
+ function renderPyExample(value) {
995
+ switch (value.kind) {
996
+ case "string":
997
+ return pyStr2(value.value);
998
+ case "integer":
999
+ return String(value.value);
1000
+ case "number":
1001
+ return String(value.value);
1002
+ case "boolean":
1003
+ return value.value ? "True" : "False";
1004
+ case "null":
1005
+ return "None";
1006
+ case "binary":
1007
+ return 'b"Example data"';
1008
+ case "enum":
1009
+ return pyLiteral(value.value);
1010
+ case "const":
1011
+ return pyLiteral(value.value);
1012
+ case "array":
1013
+ return `[${renderPyExample(value.item)}]`;
1014
+ case "map":
1015
+ return `{"key": ${renderPyExample(value.value)}}`;
1016
+ case "object":
1017
+ return value.fields.length === 0 ? "{}" : `{${value.fields.map((f) => `${pyStr2(f.name)}: ${renderPyExample(f.value)}`).join(", ")}}`;
1018
+ case "union":
1019
+ return renderPyExample(value.variant);
1020
+ default:
1021
+ return "None";
1022
+ }
1023
+ }
1024
+ function pyLiteral(v) {
1025
+ if (v === null || v === void 0) return "None";
1026
+ if (typeof v === "boolean") return v ? "True" : "False";
1027
+ if (typeof v === "number") return String(v);
1028
+ return pyStr2(String(v));
1029
+ }
1030
+ function pyStr2(s) {
1031
+ return JSON.stringify(s);
1032
+ }
1033
+
1034
+ // src/tests-py.ts
1035
+ var DEFAULT_BASE_URL = "http://127.0.0.1:4010";
1036
+ function testUtilsPy() {
1037
+ return `from __future__ import annotations
1038
+
1039
+ import typing
1040
+ from typing import Any
1041
+
1042
+
1043
+ def assert_matches_type(expected_type: Any, value: Any, *, path: Any = None) -> None:
1044
+ """Pragmatic structural check for the generated test suite.
1045
+
1046
+ Verifies the SHAPE of a response without being strict about deep generics:
1047
+ dataclass instances, the vendored pagination containers, primitives, lists
1048
+ and dicts are all accepted. A parameterized generic (e.g. CursorPage[Pet],
1049
+ list[str]) is matched against its ORIGIN only; Any / object / typing
1050
+ constructs (Optional, Union, ...) always match.
1051
+ """
1052
+ origin = typing.get_origin(expected_type)
1053
+ if origin is not None:
1054
+ expected_type = origin
1055
+ if expected_type is Any or expected_type is object or expected_type is None:
1056
+ return
1057
+ if not isinstance(expected_type, type):
1058
+ return
1059
+ assert isinstance(value, expected_type), (
1060
+ f"expected {getattr(expected_type, '__name__', expected_type)!r}, "
1061
+ f"got {type(value).__name__!r} (path={path})"
1062
+ )
1063
+ `;
1064
+ }
1065
+ function testConftestPy(pkg) {
1066
+ return `from __future__ import annotations
1067
+
1068
+ import os
1069
+
1070
+ import pytest
1071
+
1072
+ from ${pkg} import Client
1073
+
1074
+ base_url = os.environ.get("TEST_API_BASE_URL", ${JSON.stringify(DEFAULT_BASE_URL)})
1075
+
1076
+
1077
+ @pytest.fixture
1078
+ def client() -> Client:
1079
+ return Client(api_key="My API Key", base_url=base_url)
1080
+ `;
1081
+ }
1082
+ function collectMethods(resource, chain, namePrefix, out) {
1083
+ for (const method of resource.methods || []) out.push({ method, chain, namePrefix });
1084
+ for (const sub of resource.resources || []) {
1085
+ const attr = snakeCase(sub.name);
1086
+ collectMethods(sub, [...chain, attr], `${namePrefix}${attr}_`, out);
1087
+ }
1088
+ }
1089
+ function firstStringPathParam(method) {
1090
+ var _a;
1091
+ for (const p of method.pathParams || []) {
1092
+ if (((_a = p.type) == null ? void 0 : _a.kind) === "scalar" && p.type.scalar === "string" && p.required !== false) return p;
1093
+ }
1094
+ return null;
1095
+ }
1096
+ function responseTypeExpr(method, types, uses, pages) {
1097
+ var _a;
1098
+ const plan = (0, import_opensdk_framework2.planOperation)(method, types);
1099
+ if (plan.binaryContentType) return "bytes";
1100
+ const page = pyPageName(plan);
1101
+ if (page) {
1102
+ pages.add(page);
1103
+ return `${page}[${pyType((_a = method.pagination) == null ? void 0 : _a.itemType, uses)}]`;
1104
+ }
1105
+ const primary = method.primaryResponse;
1106
+ if (!primary) return null;
1107
+ return pyType(primary, uses);
1108
+ }
1109
+ function renderCallArgs(ex) {
1110
+ const parts = ex.pathArgs.map((pa) => renderPyExample(pa.value));
1111
+ for (const f of ex.fields) parts.push(`${snakeCase(f.name)}=${renderPyExample(f.value)}`);
1112
+ return parts.join(", ");
1113
+ }
1114
+ function renderMethodTest(name, call, responseType) {
1115
+ const lines = [` def ${name}(self, client: Client) -> None:`];
1116
+ if (responseType) {
1117
+ lines.push(` result = ${call}`);
1118
+ lines.push(` assert_matches_type(${responseType}, result, path=["response"])`);
1119
+ } else {
1120
+ lines.push(` ${call}`);
1121
+ }
1122
+ return lines.join("\n");
1123
+ }
1124
+ function renderPathParamsTest(name, callChain, ex, target) {
1125
+ const n = snakeCase(target.name);
1126
+ const parts = [];
1127
+ for (const pa of ex.pathArgs) parts.push(pa.param === target ? '""' : renderPyExample(pa.value));
1128
+ for (const f of ex.fields) parts.push(`${snakeCase(f.name)}=${renderPyExample(f.value)}`);
1129
+ return [
1130
+ ` def ${name}(self, client: Client) -> None:`,
1131
+ ` with pytest.raises(ValueError, match=r"Expected a non-empty value for \`${n}\` but received ''"):`,
1132
+ ` ${callChain}(${parts.join(", ")})`
1133
+ ].join("\n");
1134
+ }
1135
+ function resourceTestPy(resource, pkg, types) {
1136
+ const uses = new PyUses();
1137
+ const pages = /* @__PURE__ */ new Set();
1138
+ let usesPytest = false;
1139
+ const collected = [];
1140
+ collectMethods(resource, [snakeCase(resource.name)], "", collected);
1141
+ const blocks = [];
1142
+ for (const { method, chain, namePrefix } of collected) {
1143
+ const action = snakeCase(method.action);
1144
+ const base = `${namePrefix}${action}`;
1145
+ const callChain = `client.${[...chain, action].join(".")}`;
1146
+ const responseType = responseTypeExpr(method, types, uses, pages);
1147
+ const required = (0, import_opensdk_framework2.planMethodExample)(method, types);
1148
+ blocks.push(renderMethodTest(`test_method_${base}`, `${callChain}(${renderCallArgs(required)})`, responseType));
1149
+ if (required.hasOptional) {
1150
+ const all = (0, import_opensdk_framework2.planMethodExample)(method, types, { withOptional: true });
1151
+ blocks.push(
1152
+ renderMethodTest(`test_method_${base}_with_all_params`, `${callChain}(${renderCallArgs(all)})`, responseType)
1153
+ );
1154
+ }
1155
+ const target = firstStringPathParam(method);
1156
+ if (target) {
1157
+ usesPytest = true;
1158
+ blocks.push(renderPathParamsTest(`test_path_params_${base}`, callChain, required, target));
1159
+ }
1160
+ }
1161
+ const groups = [["from __future__ import annotations"]];
1162
+ const typingLine = uses.typingImport();
1163
+ if (typingLine) groups.push([typingLine]);
1164
+ if (usesPytest) groups.push(["import pytest"]);
1165
+ const local = ["from tests.utils import assert_matches_type", `from ${pkg} import Client`, `from ${pkg}.models import * # noqa: F401,F403`];
1166
+ if (pages.size > 0) {
1167
+ const names = ["CursorPage", "Page"].filter((n) => pages.has(n));
1168
+ local.push(`from ${pkg}._pagination import ${names.join(", ")}`);
1169
+ }
1170
+ groups.push(local);
1171
+ const imports = groups.map((g) => g.join("\n")).join("\n\n");
1172
+ const body = blocks.length ? blocks.join("\n\n") : " pass";
1173
+ return `${imports}
1174
+
1175
+
1176
+ class Test${pascalCase(resource.name)}:
1177
+ ${body}
1178
+ `;
1179
+ }
1180
+
1181
+ // src/emitter.ts
1182
+ var resolve = (spec, ctx) => resolvePythonOptions(spec, ctx.emitterOptions);
1183
+ var pythonEmitter = {
1184
+ language: "python",
1185
+ fileHeader() {
1186
+ return "Code generated by opensdk. DO NOT EDIT.";
1187
+ },
1188
+ generateProject(spec, ctx) {
1189
+ const { pkg } = resolve(spec, ctx);
1190
+ return [{ path: "pyproject.toml", content: pyproject(pkg, spec), writeMode: "skipIfExists" }];
1191
+ },
1192
+ generateClient(spec, ctx) {
1193
+ const { pkg, envVar } = resolve(spec, ctx);
1194
+ const errors = ["APIError", ...errorClassNames(spec)];
1195
+ const all = ["Client", ...errors].sort();
1196
+ const init = `from ._client import Client
1197
+ from ._transport import ${errors.join(", ")}
1198
+
1199
+ __all__ = [${all.map((n) => JSON.stringify(n)).join(", ")}]
1200
+ `;
1201
+ return [
1202
+ { path: `${pkg}/__init__.py`, content: init },
1203
+ { path: `${pkg}/_client.py`, content: clientPy(spec, envVar) }
1204
+ ];
1205
+ },
1206
+ // models.py is emitted even for an empty symbol table: resources.py
1207
+ // star-imports it, so the module must always exist.
1208
+ generateTypes(_types, ctx) {
1209
+ const { pkg } = resolve(ctx.spec, ctx);
1210
+ return [{ path: `${pkg}/models.py`, content: modelsPy(ctx.spec) }];
1211
+ },
1212
+ generateResources(_resources, ctx) {
1213
+ const { pkg } = resolve(ctx.spec, ctx);
1214
+ return [{ path: `${pkg}/resources.py`, content: resourcesPy(ctx.spec, ctx.types) }];
1215
+ },
1216
+ generateRuntime(spec, ctx) {
1217
+ const { pkg, baseURL } = resolve(spec, ctx);
1218
+ const files = [{ path: `${pkg}/_transport.py`, content: transportPy(spec, pkg, baseURL) }];
1219
+ if ((0, import_opensdk_core3.walkMethods)(spec).some(({ method }) => pyPageName((0, import_opensdk_framework3.planOperation)(method, ctx.types)) !== null)) {
1220
+ files.push({ path: `${pkg}/_pagination.py`, content: paginationPy() });
1221
+ }
1222
+ return files;
1223
+ },
1224
+ // The SDK's own pytest suite (openai-python's tests/api_resources/*). SYNC
1225
+ // only — no async/raw/streaming client yet (follow-ups). Off via
1226
+ // emitterOptions.tests === false; default ON. One test file per top-level
1227
+ // resource plus the shared conftest fixture + assert_matches_type helper.
1228
+ generateTests(spec, ctx) {
1229
+ if (ctx.emitterOptions.tests === false) return [];
1230
+ const { pkg } = resolve(spec, ctx);
1231
+ const resources = spec.resources || [];
1232
+ if (resources.length === 0) return [];
1233
+ const files = [
1234
+ { path: "tests/utils.py", content: testUtilsPy() },
1235
+ { path: "tests/conftest.py", content: testConftestPy(pkg) }
1236
+ ];
1237
+ for (const r of resources) {
1238
+ files.push({ path: `tests/test_${snakeCase(r.name)}.py`, content: resourceTestPy(r, pkg, ctx.types) });
1239
+ }
1240
+ return files;
1241
+ }
1242
+ };
1243
+ function opensdkPython(spec, options = {}) {
1244
+ return (0, import_opensdk_framework3.generate)(spec, pythonEmitter, options);
1245
+ }
1246
+
1247
+ // src/publish.ts
1248
+ var import_opensdk_framework4 = require("@xyd-js/opensdk-framework");
1249
+ function publishPython(dir, opts = {}) {
1250
+ (0, import_opensdk_framework4.runCommand)("python3", ["-m", "build"], { cwd: dir });
1251
+ if (opts.dryRun) return;
1252
+ const args = ["upload"];
1253
+ if (opts.registry) args.push("--repository-url", opts.registry);
1254
+ args.push("dist/*");
1255
+ (0, import_opensdk_framework4.runCommand)("twine", args, {
1256
+ cwd: dir,
1257
+ env: {
1258
+ ...process.env,
1259
+ TWINE_USERNAME: process.env.TWINE_USERNAME ?? "__token__",
1260
+ TWINE_PASSWORD: opts.token ?? process.env.TWINE_PASSWORD ?? "opensdk"
1261
+ }
1262
+ });
1263
+ }
1264
+
1265
+ // src/index.ts
1266
+ var import_opensdk_framework5 = require("@xyd-js/opensdk-framework");
1267
+ // Annotate the CommonJS export names for ESM import in node:
1268
+ 0 && (module.exports = {
1269
+ opensdkPython,
1270
+ publishPython,
1271
+ pythonEmitter,
1272
+ writeProject
1273
+ });
1274
+ //# sourceMappingURL=index.cjs.map