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