@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.
- package/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__create/input.json +325 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__create/output.py +26 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__delete/input.json +201 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__list/input.json +400 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__retrieve/input.json +304 -0
- package/__fixtures__/-2.complex.openai/admin__organization__admin_api_keys__retrieve/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__audit_logs__list/input.json +2602 -0
- package/__fixtures__/-2.complex.openai/admin__organization__audit_logs__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__activate__create/input.json +308 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__activate__create/output.py +32 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__create/input.json +308 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__create/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__deactivate__create/input.json +308 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__deactivate__create/output.py +32 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__delete/input.json +196 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__list/input.json +356 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__retrieve/input.json +300 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__retrieve/output.py +30 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__update/input.json +310 -0
- package/__fixtures__/-2.complex.openai/admin__organization__certificates__update/output.py +30 -0
- package/__fixtures__/-2.complex.openai/admin__organization__costs__list/input.json +1062 -0
- package/__fixtures__/-2.complex.openai/admin__organization__costs__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__create/input.json +239 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__create/output.py +26 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__delete/input.json +206 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__list/input.json +316 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__create/input.json +364 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__create/output.py +34 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__delete/input.json +210 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__list/input.json +398 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__roles__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__update/input.json +241 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__update/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__users__create/input.json +237 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__users__create/output.py +34 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__users__delete/input.json +211 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__users__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__users__list/input.json +314 -0
- package/__fixtures__/-2.complex.openai/admin__organization__groups__users__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__create/input.json +386 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__create/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__delete/input.json +203 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__list/input.json +414 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__retrieve/input.json +337 -0
- package/__fixtures__/-2.complex.openai/admin__organization__invites__retrieve/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__delete/input.json +279 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__list/input.json +475 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__retrieve/input.json +400 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__api_keys__retrieve/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__archive/input.json +247 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__archive/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__activate__create/input.json +324 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__activate__create/output.py +40 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__deactivate__create/input.json +324 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__deactivate__create/output.py +40 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__list/input.json +372 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__certificates__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__create/input.json +281 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__create/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__create/input.json +274 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__create/output.py +34 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__delete/input.json +211 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__list/input.json +342 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__groups__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__list/input.json +330 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__list_rate_limits/input.json +358 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__list_rate_limits/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__update_rate_limit/input.json +407 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__rate_limits__update_rate_limit/output.py +38 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__retrieve/input.json +247 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__retrieve/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__create/input.json +372 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__create/output.py +34 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__delete/input.json +216 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__list/input.json +391 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__retrieve/input.json +253 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__service_accounts__retrieve/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__update/input.json +356 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__update/output.py +30 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__create/input.json +349 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__create/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__delete/input.json +279 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__list/input.json +387 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__retrieve/input.json +250 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__retrieve/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__update/input.json +339 -0
- package/__fixtures__/-2.complex.openai/admin__organization__projects__users__update/output.py +38 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__create/input.json +283 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__create/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__delete/input.json +206 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__list/input.json +338 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__update/input.json +296 -0
- package/__fixtures__/-2.complex.openai/admin__organization__roles__update/output.py +30 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_speeches__list/input.json +1108 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_speeches__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_transcriptions__list/input.json +1108 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__audio_transcriptions__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__code_interpreter_sessions__list/input.json +1054 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__code_interpreter_sessions__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__completions__list/input.json +1123 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__completions__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__embeddings__list/input.json +1108 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__embeddings__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__images__list/input.json +1176 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__images__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__moderations__list/input.json +1108 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__moderations__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__vector_stores__list/input.json +1054 -0
- package/__fixtures__/-2.complex.openai/admin__organization__usage__vector_stores__list/output.py +35 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__delete/input.json +202 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__list/input.json +557 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__retrieve/input.json +472 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__retrieve/output.py +28 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__roles__create/input.json +611 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__roles__create/output.py +34 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__roles__delete/input.json +210 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__roles__delete/output.py +36 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__roles__list/input.json +398 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__roles__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__update/input.json +528 -0
- package/__fixtures__/-2.complex.openai/admin__organization__users__update/output.py +30 -0
- package/__fixtures__/-2.complex.openai/audio__speech__create/input.json +388 -0
- package/__fixtures__/-2.complex.openai/audio__speech__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__transcriptions__create/input.json +999 -0
- package/__fixtures__/-2.complex.openai/audio__transcriptions__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__translations__create/input.json +430 -0
- package/__fixtures__/-2.complex.openai/audio__translations__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__create/input.json +244 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__delete/input.json +190 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__delete/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__list/input.json +285 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__list/output.py +23 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__retrieve/input.json +212 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__retrieve/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__update/input.json +236 -0
- package/__fixtures__/-2.complex.openai/audio__voice_consents__update/output.py +22 -0
- package/__fixtures__/-2.complex.openai/audio__voices__create/input.json +235 -0
- package/__fixtures__/-2.complex.openai/audio__voices__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/batches__cancel/input.json +594 -0
- package/__fixtures__/-2.complex.openai/batches__cancel/output.py +16 -0
- package/__fixtures__/-2.complex.openai/batches__create/input.json +701 -0
- package/__fixtures__/-2.complex.openai/batches__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/batches__list/input.json +665 -0
- package/__fixtures__/-2.complex.openai/batches__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/batches__retrieve/input.json +594 -0
- package/__fixtures__/-2.complex.openai/batches__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__create/input.json +1029 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__delete/input.json +190 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__delete/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__list/input.json +796 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__list/output.py +23 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__retrieve/input.json +694 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__retrieve/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__update/input.json +1045 -0
- package/__fixtures__/-2.complex.openai/beta__assistants__update/output.py +24 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__cancel/input.json +482 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__cancel/output.py +28 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__create/input.json +738 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__sessions__create/output.py +28 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__delete/input.json +200 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__delete/output.py +28 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__items__list/input.json +1218 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__items__list/output.py +37 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__list/input.json +444 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__list/output.py +29 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__retrieve/input.json +328 -0
- package/__fixtures__/-2.complex.openai/beta__chat_kit__threads__retrieve/output.py +28 -0
- package/__fixtures__/-2.complex.openai/beta__threads__create/input.json +665 -0
- package/__fixtures__/-2.complex.openai/beta__threads__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__threads__delete/input.json +189 -0
- package/__fixtures__/-2.complex.openai/beta__threads__delete/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__create/input.json +938 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__create/output.py +30 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__delete/input.json +203 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__delete/output.py +30 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__list/input.json +945 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__list/output.py +31 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__retrieve/input.json +832 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__retrieve/output.py +30 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__update/input.json +855 -0
- package/__fixtures__/-2.complex.openai/beta__threads__messages__update/output.py +32 -0
- package/__fixtures__/-2.complex.openai/beta__threads__new_and_run/input.json +1899 -0
- package/__fixtures__/-2.complex.openai/beta__threads__new_and_run/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__threads__retrieve/input.json +283 -0
- package/__fixtures__/-2.complex.openai/beta__threads__retrieve/output.py +22 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__cancel/input.json +1181 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__cancel/output.py +30 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__create/input.json +1851 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__create/output.py +30 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__list/input.json +1285 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__list/output.py +31 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__retrieve/input.json +1181 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__retrieve/output.py +30 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__list/input.json +1066 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__list/output.py +39 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__retrieve/input.json +964 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__steps__retrieve/output.py +40 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__submit_tool_outputs__create/input.json +1246 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__submit_tool_outputs__create/output.py +38 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__update/input.json +1204 -0
- package/__fixtures__/-2.complex.openai/beta__threads__runs__update/output.py +32 -0
- package/__fixtures__/-2.complex.openai/beta__threads__update/input.json +315 -0
- package/__fixtures__/-2.complex.openai/beta__threads__update/output.py +24 -0
- package/__fixtures__/-2.complex.openai/chat__completions__create/input.json +3325 -0
- package/__fixtures__/-2.complex.openai/chat__completions__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/chat__completions__delete/input.json +192 -0
- package/__fixtures__/-2.complex.openai/chat__completions__delete/output.py +22 -0
- package/__fixtures__/-2.complex.openai/chat__completions__list/input.json +1069 -0
- package/__fixtures__/-2.complex.openai/chat__completions__list/output.py +23 -0
- package/__fixtures__/-2.complex.openai/chat__completions__messages__list/input.json +770 -0
- package/__fixtures__/-2.complex.openai/chat__completions__messages__list/output.py +31 -0
- package/__fixtures__/-2.complex.openai/chat__completions__retrieve/input.json +938 -0
- package/__fixtures__/-2.complex.openai/chat__completions__retrieve/output.py +22 -0
- package/__fixtures__/-2.complex.openai/chat__completions__update/input.json +973 -0
- package/__fixtures__/-2.complex.openai/chat__completions__update/output.py +22 -0
- package/__fixtures__/-2.complex.openai/completions__create/input.json +788 -0
- package/__fixtures__/-2.complex.openai/completions__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/containers__create/input.json +671 -0
- package/__fixtures__/-2.complex.openai/containers__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/containers__delete/input.json +142 -0
- package/__fixtures__/-2.complex.openai/containers__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/containers__files__content/input.json +154 -0
- package/__fixtures__/-2.complex.openai/containers__files__content/output.py +24 -0
- package/__fixtures__/-2.complex.openai/containers__files__create/input.json +261 -0
- package/__fixtures__/-2.complex.openai/containers__files__create/output.py +24 -0
- package/__fixtures__/-2.complex.openai/containers__files__delete/input.json +154 -0
- package/__fixtures__/-2.complex.openai/containers__files__delete/output.py +24 -0
- package/__fixtures__/-2.complex.openai/containers__files__list/input.json +337 -0
- package/__fixtures__/-2.complex.openai/containers__files__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/containers__files__retrieve/input.json +235 -0
- package/__fixtures__/-2.complex.openai/containers__files__retrieve/output.py +24 -0
- package/__fixtures__/-2.complex.openai/containers__list/input.json +438 -0
- package/__fixtures__/-2.complex.openai/containers__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/containers__retrieve/input.json +329 -0
- package/__fixtures__/-2.complex.openai/containers__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/conversations__create/input.json +6737 -0
- package/__fixtures__/-2.complex.openai/conversations__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/conversations__delete/input.json +186 -0
- package/__fixtures__/-2.complex.openai/conversations__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/conversations__items__create/input.json +8352 -0
- package/__fixtures__/-2.complex.openai/conversations__items__create/output.py +25 -0
- package/__fixtures__/-2.complex.openai/conversations__items__delete/input.json +213 -0
- package/__fixtures__/-2.complex.openai/conversations__items__delete/output.py +24 -0
- package/__fixtures__/-2.complex.openai/conversations__items__list/input.json +6695 -0
- package/__fixtures__/-2.complex.openai/conversations__items__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/conversations__items__retrieve/input.json +6597 -0
- package/__fixtures__/-2.complex.openai/conversations__items__retrieve/output.py +26 -0
- package/__fixtures__/-2.complex.openai/conversations__retrieve/input.json +198 -0
- package/__fixtures__/-2.complex.openai/conversations__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/conversations__update/input.json +233 -0
- package/__fixtures__/-2.complex.openai/conversations__update/output.py +16 -0
- package/__fixtures__/-2.complex.openai/embeddings__create/input.json +395 -0
- package/__fixtures__/-2.complex.openai/embeddings__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/evals__create/input.json +1424 -0
- package/__fixtures__/-2.complex.openai/evals__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/evals__delete/input.json +232 -0
- package/__fixtures__/-2.complex.openai/evals__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/evals__list/input.json +1251 -0
- package/__fixtures__/-2.complex.openai/evals__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/evals__retrieve/input.json +1127 -0
- package/__fixtures__/-2.complex.openai/evals__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/evals__runs__cancel/input.json +4445 -0
- package/__fixtures__/-2.complex.openai/evals__runs__cancel/output.py +24 -0
- package/__fixtures__/-2.complex.openai/evals__runs__create/input.json +4526 -0
- package/__fixtures__/-2.complex.openai/evals__runs__create/output.py +24 -0
- package/__fixtures__/-2.complex.openai/evals__runs__delete/input.json +246 -0
- package/__fixtures__/-2.complex.openai/evals__runs__delete/output.py +24 -0
- package/__fixtures__/-2.complex.openai/evals__runs__list/input.json +4579 -0
- package/__fixtures__/-2.complex.openai/evals__runs__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/evals__runs__output_items__list/input.json +685 -0
- package/__fixtures__/-2.complex.openai/evals__runs__output_items__list/output.py +33 -0
- package/__fixtures__/-2.complex.openai/evals__runs__output_items__retrieve/input.json +560 -0
- package/__fixtures__/-2.complex.openai/evals__runs__output_items__retrieve/output.py +32 -0
- package/__fixtures__/-2.complex.openai/evals__runs__retrieve/input.json +4445 -0
- package/__fixtures__/-2.complex.openai/evals__runs__retrieve/output.py +24 -0
- package/__fixtures__/-2.complex.openai/evals__update/input.json +1160 -0
- package/__fixtures__/-2.complex.openai/evals__update/output.py +18 -0
- package/__fixtures__/-2.complex.openai/files__content/input.json +151 -0
- package/__fixtures__/-2.complex.openai/files__content/output.py +16 -0
- package/__fixtures__/-2.complex.openai/files__create/input.json +379 -0
- package/__fixtures__/-2.complex.openai/files__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/files__delete/input.json +184 -0
- package/__fixtures__/-2.complex.openai/files__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/files__list/input.json +397 -0
- package/__fixtures__/-2.complex.openai/files__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/files__retrieve/input.json +295 -0
- package/__fixtures__/-2.complex.openai/files__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__run__create/input.json +1225 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__run__create/output.py +34 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__validate__create/input.json +991 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__alpha__graders__validate__create/output.py +32 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__create/input.json +297 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__create/output.py +29 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__delete/input.json +208 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__delete/output.py +30 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__list/input.json +325 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__checkpoints__permissions__list/output.py +31 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__cancel/input.json +1645 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__cancel/output.py +22 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__checkpoints__list/input.json +383 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__checkpoints__list/output.py +31 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__create/input.json +1887 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list/input.json +1714 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list/output.py +23 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list_events/input.json +330 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__list_events/output.py +25 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__pause/input.json +1645 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__pause/output.py +22 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__resume/input.json +1645 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__resume/output.py +22 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__retrieve/input.json +1645 -0
- package/__fixtures__/-2.complex.openai/fine_tuning__jobs__retrieve/output.py +22 -0
- package/__fixtures__/-2.complex.openai/images__edits__create/input.json +744 -0
- package/__fixtures__/-2.complex.openai/images__edits__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/images__generations__create/input.json +789 -0
- package/__fixtures__/-2.complex.openai/images__generations__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/images__variations__create/input.json +550 -0
- package/__fixtures__/-2.complex.openai/images__variations__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/models__delete/input.json +184 -0
- package/__fixtures__/-2.complex.openai/models__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/models__list/input.json +221 -0
- package/__fixtures__/-2.complex.openai/models__list/output.py +15 -0
- package/__fixtures__/-2.complex.openai/models__retrieve/input.json +199 -0
- package/__fixtures__/-2.complex.openai/models__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/moderations__create/input.json +831 -0
- package/__fixtures__/-2.complex.openai/moderations__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/projects__groups__roles__create/input.json +368 -0
- package/__fixtures__/-2.complex.openai/projects__groups__roles__create/output.py +30 -0
- package/__fixtures__/-2.complex.openai/projects__groups__roles__delete/input.json +214 -0
- package/__fixtures__/-2.complex.openai/projects__groups__roles__delete/output.py +32 -0
- package/__fixtures__/-2.complex.openai/projects__groups__roles__list/input.json +402 -0
- package/__fixtures__/-2.complex.openai/projects__groups__roles__list/output.py +33 -0
- package/__fixtures__/-2.complex.openai/projects__roles__create/input.json +289 -0
- package/__fixtures__/-2.complex.openai/projects__roles__create/output.py +24 -0
- package/__fixtures__/-2.complex.openai/projects__roles__delete/input.json +210 -0
- package/__fixtures__/-2.complex.openai/projects__roles__delete/output.py +24 -0
- package/__fixtures__/-2.complex.openai/projects__roles__list/input.json +344 -0
- package/__fixtures__/-2.complex.openai/projects__roles__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/projects__roles__update/input.json +300 -0
- package/__fixtures__/-2.complex.openai/projects__roles__update/output.py +26 -0
- package/__fixtures__/-2.complex.openai/projects__users__roles__create/input.json +615 -0
- package/__fixtures__/-2.complex.openai/projects__users__roles__create/output.py +30 -0
- package/__fixtures__/-2.complex.openai/projects__users__roles__delete/input.json +214 -0
- package/__fixtures__/-2.complex.openai/projects__users__roles__delete/output.py +32 -0
- package/__fixtures__/-2.complex.openai/projects__users__roles__list/input.json +402 -0
- package/__fixtures__/-2.complex.openai/projects__users__roles__list/output.py +33 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__accept/input.json +1768 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__accept/output.py +24 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__create/input.json +1790 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__hangup/input.json +147 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__hangup/output.py +22 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__refer/input.json +175 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__refer/output.py +22 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__reject/input.json +175 -0
- package/__fixtures__/-2.complex.openai/realtime__calls__reject/output.py +24 -0
- package/__fixtures__/-2.complex.openai/realtime__client_secrets__create/input.json +2407 -0
- package/__fixtures__/-2.complex.openai/realtime__client_secrets__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/realtime__sessions__create/input.json +1400 -0
- package/__fixtures__/-2.complex.openai/realtime__sessions__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/realtime__transcription_sessions__create/input.json +562 -0
- package/__fixtures__/-2.complex.openai/realtime__transcription_sessions__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/realtime__translations__client_secrets__create/input.json +498 -0
- package/__fixtures__/-2.complex.openai/realtime__translations__client_secrets__create/output.py +28 -0
- package/__fixtures__/-2.complex.openai/responses__cancel/input.json +9526 -0
- package/__fixtures__/-2.complex.openai/responses__cancel/output.py +16 -0
- package/__fixtures__/-2.complex.openai/responses__compact__create/input.json +8721 -0
- package/__fixtures__/-2.complex.openai/responses__compact__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/responses__create/input.json +9862 -0
- package/__fixtures__/-2.complex.openai/responses__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/responses__delete/input.json +194 -0
- package/__fixtures__/-2.complex.openai/responses__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/responses__input_items__list/input.json +6686 -0
- package/__fixtures__/-2.complex.openai/responses__input_items__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/responses__input_tokens__count/input.json +7368 -0
- package/__fixtures__/-2.complex.openai/responses__input_tokens__count/output.py +22 -0
- package/__fixtures__/-2.complex.openai/responses__retrieve/input.json +9550 -0
- package/__fixtures__/-2.complex.openai/responses__retrieve/output.py +18 -0
- package/__fixtures__/-2.complex.openai/skills__content/input.json +152 -0
- package/__fixtures__/-2.complex.openai/skills__content/output.py +16 -0
- package/__fixtures__/-2.complex.openai/skills__create/input.json +258 -0
- package/__fixtures__/-2.complex.openai/skills__create/output.py +14 -0
- package/__fixtures__/-2.complex.openai/skills__delete/input.json +186 -0
- package/__fixtures__/-2.complex.openai/skills__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/skills__list/input.json +323 -0
- package/__fixtures__/-2.complex.openai/skills__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/skills__retrieve/input.json +226 -0
- package/__fixtures__/-2.complex.openai/skills__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/skills__update/input.json +251 -0
- package/__fixtures__/-2.complex.openai/skills__update/output.py +16 -0
- package/__fixtures__/-2.complex.openai/skills__versions__content/input.json +166 -0
- package/__fixtures__/-2.complex.openai/skills__versions__content/output.py +24 -0
- package/__fixtures__/-2.complex.openai/skills__versions__create/input.json +284 -0
- package/__fixtures__/-2.complex.openai/skills__versions__create/output.py +24 -0
- package/__fixtures__/-2.complex.openai/skills__versions__delete/input.json +209 -0
- package/__fixtures__/-2.complex.openai/skills__versions__delete/output.py +24 -0
- package/__fixtures__/-2.complex.openai/skills__versions__list/input.json +341 -0
- package/__fixtures__/-2.complex.openai/skills__versions__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/skills__versions__retrieve/input.json +240 -0
- package/__fixtures__/-2.complex.openai/skills__versions__retrieve/output.py +24 -0
- package/__fixtures__/-2.complex.openai/uploads__cancel/input.json +407 -0
- package/__fixtures__/-2.complex.openai/uploads__cancel/output.py +16 -0
- package/__fixtures__/-2.complex.openai/uploads__complete/input.json +443 -0
- package/__fixtures__/-2.complex.openai/uploads__complete/output.py +18 -0
- package/__fixtures__/-2.complex.openai/uploads__create/input.json +501 -0
- package/__fixtures__/-2.complex.openai/uploads__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/uploads__parts__create/input.json +229 -0
- package/__fixtures__/-2.complex.openai/uploads__parts__create/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__create/input.json +507 -0
- package/__fixtures__/-2.complex.openai/vector_stores__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/vector_stores__delete/input.json +184 -0
- package/__fixtures__/-2.complex.openai/vector_stores__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__cancel/input.json +300 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__cancel/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__create/input.json +314 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__list_files/input.json +571 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__list_files/output.py +27 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__retrieve/input.json +302 -0
- package/__fixtures__/-2.complex.openai/vector_stores__file_batches__retrieve/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__content/input.json +249 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__content/output.py +25 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__create/input.json +527 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__create/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__delete/input.json +198 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__delete/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__list/input.json +562 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__list/output.py +25 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__retrieve/input.json +432 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__retrieve/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__update/input.json +455 -0
- package/__fixtures__/-2.complex.openai/vector_stores__files__update/output.py +24 -0
- package/__fixtures__/-2.complex.openai/vector_stores__list/input.json +468 -0
- package/__fixtures__/-2.complex.openai/vector_stores__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/vector_stores__retrieve/input.json +366 -0
- package/__fixtures__/-2.complex.openai/vector_stores__retrieve/output.py +16 -0
- package/__fixtures__/-2.complex.openai/vector_stores__search/input.json +637 -0
- package/__fixtures__/-2.complex.openai/vector_stores__search/output.py +19 -0
- package/__fixtures__/-2.complex.openai/vector_stores__update/input.json +409 -0
- package/__fixtures__/-2.complex.openai/vector_stores__update/output.py +18 -0
- package/__fixtures__/-2.complex.openai/videos__characters__create/input.json +216 -0
- package/__fixtures__/-2.complex.openai/videos__characters__create/output.py +22 -0
- package/__fixtures__/-2.complex.openai/videos__characters__retrieve/input.json +193 -0
- package/__fixtures__/-2.complex.openai/videos__characters__retrieve/output.py +22 -0
- package/__fixtures__/-2.complex.openai/videos__create/input.json +465 -0
- package/__fixtures__/-2.complex.openai/videos__create/output.py +16 -0
- package/__fixtures__/-2.complex.openai/videos__delete/input.json +190 -0
- package/__fixtures__/-2.complex.openai/videos__delete/output.py +16 -0
- package/__fixtures__/-2.complex.openai/videos__download_content/input.json +181 -0
- package/__fixtures__/-2.complex.openai/videos__download_content/output.py +18 -0
- package/__fixtures__/-2.complex.openai/videos__edits__create/input.json +422 -0
- package/__fixtures__/-2.complex.openai/videos__edits__create/output.py +20 -0
- package/__fixtures__/-2.complex.openai/videos__extensions__create/input.json +446 -0
- package/__fixtures__/-2.complex.openai/videos__extensions__create/output.py +20 -0
- package/__fixtures__/-2.complex.openai/videos__list/input.json +477 -0
- package/__fixtures__/-2.complex.openai/videos__list/output.py +17 -0
- package/__fixtures__/-2.complex.openai/videos__remix/input.json +405 -0
- package/__fixtures__/-2.complex.openai/videos__remix/output.py +16 -0
- package/__fixtures__/-2.complex.openai/videos__retrieve/input.json +380 -0
- package/__fixtures__/-2.complex.openai/videos__retrieve/output.py +16 -0
- package/__fixtures__/1.basic/input.json +249 -0
- package/__fixtures__/1.basic/output/petstore/__init__.py +6 -0
- package/__fixtures__/1.basic/output/petstore/_client.py +21 -0
- package/__fixtures__/1.basic/output/petstore/_pagination.py +42 -0
- package/__fixtures__/1.basic/output/petstore/_transport.py +391 -0
- package/__fixtures__/1.basic/output/petstore/models.py +33 -0
- package/__fixtures__/1.basic/output/petstore/resources.py +25 -0
- package/__fixtures__/1.basic/output/pyproject.toml +12 -0
- package/__fixtures__/1.basic/output/tests/conftest.py +16 -0
- package/__fixtures__/1.basic/output/tests/test_pets.py +36 -0
- package/__fixtures__/1.basic/output/tests/utils.py +28 -0
- package/__fixtures__/2.wire/input.json +351 -0
- package/__fixtures__/2.wire/output/pyproject.toml +12 -0
- package/__fixtures__/2.wire/output/tests/conftest.py +16 -0
- package/__fixtures__/2.wire/output/tests/test_items.py +18 -0
- package/__fixtures__/2.wire/output/tests/test_tokens.py +17 -0
- package/__fixtures__/2.wire/output/tests/test_uploads.py +27 -0
- package/__fixtures__/2.wire/output/tests/utils.py +28 -0
- package/__fixtures__/2.wire/output/wire_service/__init__.py +6 -0
- package/__fixtures__/2.wire/output/wire_service/_client.py +23 -0
- package/__fixtures__/2.wire/output/wire_service/_pagination.py +42 -0
- package/__fixtures__/2.wire/output/wire_service/_transport.py +391 -0
- package/__fixtures__/2.wire/output/wire_service/models.py +44 -0
- package/__fixtures__/2.wire/output/wire_service/resources.py +38 -0
- package/__tests__/docs.test.ts +115 -0
- package/__tests__/e2e/harness.ts +79 -0
- package/__tests__/e2e/openai.test.ts +14 -0
- package/__tests__/e2e/publish.test.ts +19 -0
- package/__tests__/opensdk-python.test.ts +134 -0
- package/__tests__/utils.ts +117 -0
- package/biome.json +25 -0
- package/dist/index.cjs +1274 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +1246 -0
- package/dist/index.js.map +1 -0
- package/index.ts +1 -0
- package/package.json +30 -0
- package/src/emitter.ts +95 -0
- package/src/example-py.ts +60 -0
- package/src/index.ts +4 -0
- package/src/method.ts +13 -0
- package/src/naming.ts +45 -0
- package/src/project.ts +446 -0
- package/src/publish.ts +22 -0
- package/src/pytype.ts +86 -0
- package/src/runtime.ts +551 -0
- package/src/tests-py.ts +197 -0
- package/src/types.ts +8 -0
- package/tsconfig.json +18 -0
- package/tsup.config.ts +19 -0
- package/vitest.config.ts +8 -0
package/src/project.ts
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Field,
|
|
3
|
+
type Method,
|
|
4
|
+
type NamedType,
|
|
5
|
+
type OpensdkSpecJson,
|
|
6
|
+
type Param,
|
|
7
|
+
type ResolvedSdkBehavior,
|
|
8
|
+
type Resource,
|
|
9
|
+
type TypeRef,
|
|
10
|
+
sdkBehavior,
|
|
11
|
+
} from '@xyd-js/opensdk-core';
|
|
12
|
+
import { type OperationPlan, planOperation } from '@xyd-js/opensdk-framework';
|
|
13
|
+
|
|
14
|
+
import { pyPageName } from './method';
|
|
15
|
+
import { pascalCase, pyModuleName, screamingSnakeCase, snakeCase } from './naming';
|
|
16
|
+
import { PyUses, isPassthroughType, optionalize, pyType } from './pytype';
|
|
17
|
+
import type { OpensdkPythonOptions } from './types';
|
|
18
|
+
|
|
19
|
+
// Pure per-file renderers for the Python SDK — the second target (after Go),
|
|
20
|
+
// proving the IR is language-agnostic. Dependency-free (stdlib urllib
|
|
21
|
+
// transport in runtime.ts); mirrors the Go emitter's minimum bar: typed
|
|
22
|
+
// signatures, decoded model returns, page containers, structured errors and
|
|
23
|
+
// wire-correct query/form/multipart encoding. Driven by the emitter plugin in
|
|
24
|
+
// emitter.ts; `opensdkPython()` there wraps it for back-compat.
|
|
25
|
+
|
|
26
|
+
export interface ResolvedPythonOptions {
|
|
27
|
+
pkg: string;
|
|
28
|
+
baseURL: string;
|
|
29
|
+
envVar: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function resolvePythonOptions(spec: OpensdkSpecJson, options: OpensdkPythonOptions): ResolvedPythonOptions {
|
|
33
|
+
const pkg = options.packageName ?? pyModuleName(spec.info.title);
|
|
34
|
+
return {
|
|
35
|
+
pkg,
|
|
36
|
+
baseURL: options.baseURL ?? spec.servers?.[0] ?? '',
|
|
37
|
+
envVar: spec.security?.find((s) => s.envVar)?.envVar ?? `${screamingSnakeCase(pkg)}_API_KEY`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The generated `pyproject.toml`: a PEP 621 project table with a `[build-system]`
|
|
43
|
+
* so `python -m build` produces an installable/publishable wheel + sdist. Publish
|
|
44
|
+
* identity (description/authors/license/urls) comes from `spec.info` — the OpenAPI
|
|
45
|
+
* `info` or an sdk.json `publish` override. Dependency-free (stdlib transport).
|
|
46
|
+
*/
|
|
47
|
+
export function pyproject(pkg: string, spec: OpensdkSpecJson): string {
|
|
48
|
+
const info = spec.info;
|
|
49
|
+
const lines = [
|
|
50
|
+
'[build-system]',
|
|
51
|
+
'requires = ["setuptools>=61"]',
|
|
52
|
+
'build-backend = "setuptools.build_meta"',
|
|
53
|
+
'',
|
|
54
|
+
'[project]',
|
|
55
|
+
`name = ${JSON.stringify(pkg.replace(/_/g, '-'))}`,
|
|
56
|
+
`version = ${JSON.stringify(info.version || '0.0.0')}`,
|
|
57
|
+
];
|
|
58
|
+
if (info.description) lines.push(`description = ${JSON.stringify(info.description)}`);
|
|
59
|
+
lines.push('requires-python = ">=3.9"');
|
|
60
|
+
if (info.contact?.name) lines.push(`authors = [{ name = ${JSON.stringify(info.contact.name)} }]`);
|
|
61
|
+
if (info.license?.identifier) lines.push(`license = { text = ${JSON.stringify(info.license.identifier)} }`);
|
|
62
|
+
const urls: string[] = [];
|
|
63
|
+
if (info.homepage) urls.push(`Homepage = ${JSON.stringify(info.homepage)}`);
|
|
64
|
+
if (info.repository) urls.push(`Repository = ${JSON.stringify(info.repository)}`);
|
|
65
|
+
if (urls.length) lines.push('', '[project.urls]', ...urls);
|
|
66
|
+
lines.push('', '[tool.setuptools.packages.find]', `include = [${JSON.stringify(pkg)}]`);
|
|
67
|
+
return `${lines.join('\n')}\n`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ---- models.py -----------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
interface ModelsCtx {
|
|
73
|
+
uses: PyUses;
|
|
74
|
+
needsField: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function modelsPy(spec: OpensdkSpecJson): string {
|
|
78
|
+
const ctx: ModelsCtx = { uses: new PyUses(), needsField: false };
|
|
79
|
+
// Ordering matters: a struct's field annotations are lazy (`from __future__
|
|
80
|
+
// import annotations`), so structs/enums may appear in any order. But an
|
|
81
|
+
// alias/union assignment `X = list[Y]` is evaluated EAGERLY at import, so Y
|
|
82
|
+
// must already be defined. Emit all structs/enums first, then the alias group
|
|
83
|
+
// topologically sorted so an alias that references another alias comes after it.
|
|
84
|
+
const types = spec.types || [];
|
|
85
|
+
const aliasKinds = new Set(['alias', 'union']);
|
|
86
|
+
const structsEnums = types.filter((t) => !aliasKinds.has(t.kind));
|
|
87
|
+
const aliases = orderAliases(types.filter((t) => aliasKinds.has(t.kind)));
|
|
88
|
+
const decls = [...structsEnums, ...aliases].map((t) => namedType(t, ctx)).filter(Boolean);
|
|
89
|
+
const lines = [
|
|
90
|
+
'from __future__ import annotations',
|
|
91
|
+
'',
|
|
92
|
+
`from dataclasses import dataclass${ctx.needsField ? ', field' : ''}`,
|
|
93
|
+
'from enum import Enum',
|
|
94
|
+
];
|
|
95
|
+
const typingLine = ctx.uses.typingImport();
|
|
96
|
+
if (typingLine) lines.push(typingLine);
|
|
97
|
+
return `${lines.join('\n')}\n\n\n${decls.join('\n\n\n')}\n`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** All named-type references inside a TypeRef tree (for alias dependency ordering). */
|
|
101
|
+
function typeRefNames(ref: TypeRef | undefined, out: Set<string>): void {
|
|
102
|
+
if (!ref) return;
|
|
103
|
+
if (ref.kind === 'ref' && ref.name) out.add(ref.name);
|
|
104
|
+
typeRefNames(ref.items as TypeRef | undefined, out);
|
|
105
|
+
typeRefNames(ref.values as TypeRef | undefined, out);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Topologically order the alias/union group so an alias whose RHS references
|
|
110
|
+
* another alias is emitted after it (the RHS is eagerly evaluated at import).
|
|
111
|
+
* References to structs/enums are ignored (already emitted above); cycles fall
|
|
112
|
+
* back to input order (unreachable for list/dict/Any alias forms).
|
|
113
|
+
*/
|
|
114
|
+
function orderAliases(aliases: NamedType[]): NamedType[] {
|
|
115
|
+
const byName = new Map(aliases.map((a) => [a.name, a]));
|
|
116
|
+
const ordered: NamedType[] = [];
|
|
117
|
+
const done = new Set<string>();
|
|
118
|
+
const visiting = new Set<string>();
|
|
119
|
+
const visit = (a: NamedType) => {
|
|
120
|
+
if (done.has(a.name) || visiting.has(a.name)) return;
|
|
121
|
+
visiting.add(a.name);
|
|
122
|
+
const refs = new Set<string>();
|
|
123
|
+
if (a.kind === 'alias') typeRefNames(a.of as TypeRef | undefined, refs);
|
|
124
|
+
for (const r of refs) {
|
|
125
|
+
const dep = byName.get(r);
|
|
126
|
+
if (dep && dep !== a) visit(dep);
|
|
127
|
+
}
|
|
128
|
+
visiting.delete(a.name);
|
|
129
|
+
done.add(a.name);
|
|
130
|
+
ordered.push(a);
|
|
131
|
+
};
|
|
132
|
+
for (const a of aliases) visit(a);
|
|
133
|
+
return ordered;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function namedType(type: NamedType, ctx: ModelsCtx): string {
|
|
137
|
+
switch (type.kind) {
|
|
138
|
+
case 'enum':
|
|
139
|
+
return enumType(type);
|
|
140
|
+
case 'alias':
|
|
141
|
+
return `${pascalCase(type.name)} = ${pyType(type.of, ctx.uses)}`;
|
|
142
|
+
case 'union':
|
|
143
|
+
ctx.uses.use('Any');
|
|
144
|
+
return `${pascalCase(type.name)} = Any`;
|
|
145
|
+
default:
|
|
146
|
+
return structType(type, ctx);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function structType(type: NamedType, ctx: ModelsCtx): string {
|
|
151
|
+
const name = pascalCase(type.name);
|
|
152
|
+
const fields = type.fields || [];
|
|
153
|
+
if (fields.length === 0) return `@dataclass\nclass ${name}:\n pass`;
|
|
154
|
+
// Required fields first (no default), then optional (Optional[...] = None).
|
|
155
|
+
const required = fields.filter((f) => f.required);
|
|
156
|
+
const optional = fields.filter((f) => !f.required);
|
|
157
|
+
const lines = [...required, ...optional].map((f) => structFieldLine(f, ctx));
|
|
158
|
+
return `@dataclass\nclass ${name}:\n${lines.join('\n')}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* One dataclass field. When the Python name differs from the wire name the
|
|
163
|
+
* raw name is kept in `field(metadata={"wire": ...})` so the runtime's
|
|
164
|
+
* encode/decode stay wire-correct.
|
|
165
|
+
*/
|
|
166
|
+
function structFieldLine(f: Field, ctx: ModelsCtx): string {
|
|
167
|
+
const py = snakeCase(f.name);
|
|
168
|
+
const type = pyType(f.type, ctx.uses);
|
|
169
|
+
const wire = py === f.name ? null : `metadata={"wire": ${JSON.stringify(f.name)}}`;
|
|
170
|
+
if (f.required) {
|
|
171
|
+
if (!wire) return ` ${py}: ${type}`;
|
|
172
|
+
ctx.needsField = true;
|
|
173
|
+
return ` ${py}: ${type} = field(${wire})`;
|
|
174
|
+
}
|
|
175
|
+
const opt = optionalize(type, ctx.uses);
|
|
176
|
+
if (!wire) return ` ${py}: ${opt} = None`;
|
|
177
|
+
ctx.needsField = true;
|
|
178
|
+
return ` ${py}: ${opt} = field(default=None, ${wire})`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function enumType(type: NamedType): string {
|
|
182
|
+
const name = pascalCase(type.name);
|
|
183
|
+
const base = type.base === 'integer' ? 'int' : 'str';
|
|
184
|
+
const values = type.values || [];
|
|
185
|
+
if (values.length === 0) return `class ${name}(${base}, Enum):\n pass`;
|
|
186
|
+
const members = values.map((v) => {
|
|
187
|
+
const member = screamingSnakeCase(String(v.name ?? v.value)) || 'VALUE';
|
|
188
|
+
const lit = base === 'int' ? String(v.value) : JSON.stringify(String(v.value));
|
|
189
|
+
return ` ${member} = ${lit}`;
|
|
190
|
+
});
|
|
191
|
+
return `class ${name}(${base}, Enum):\n${members.join('\n')}`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ---- resources.py --------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
interface ResourcesCtx {
|
|
197
|
+
types: Map<string, NamedType>;
|
|
198
|
+
/** The resolved runtime-behavior policies (sdk block over canonical defaults). */
|
|
199
|
+
behavior: ResolvedSdkBehavior;
|
|
200
|
+
uses: PyUses;
|
|
201
|
+
/** Extra names imported from ._transport (decode, join_csv). */
|
|
202
|
+
transportImports: Set<string>;
|
|
203
|
+
/** Page containers imported from ._pagination. */
|
|
204
|
+
pages: Set<'CursorPage' | 'Page'>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function resourcesPy(spec: OpensdkSpecJson, types: Map<string, NamedType>): string {
|
|
208
|
+
const ctx: ResourcesCtx = {
|
|
209
|
+
types,
|
|
210
|
+
behavior: sdkBehavior(spec),
|
|
211
|
+
uses: new PyUses(),
|
|
212
|
+
transportImports: new Set(),
|
|
213
|
+
pages: new Set(),
|
|
214
|
+
};
|
|
215
|
+
const classes: string[] = [];
|
|
216
|
+
const emit = (resources: Resource[], parent: string[]) => {
|
|
217
|
+
for (const r of resources) {
|
|
218
|
+
const segments = [...parent, r.name];
|
|
219
|
+
classes.push(resourceClass(r, segments, ctx));
|
|
220
|
+
if (r.resources?.length) emit(r.resources, segments);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
emit(spec.resources || [], []);
|
|
224
|
+
|
|
225
|
+
const lines = ['from __future__ import annotations', ''];
|
|
226
|
+
const typingLine = ctx.uses.typingImport();
|
|
227
|
+
if (typingLine) lines.push(typingLine, '');
|
|
228
|
+
if (ctx.pages.size > 0) {
|
|
229
|
+
const pageNames = (['CursorPage', 'Page'] as const).filter((n) => ctx.pages.has(n));
|
|
230
|
+
lines.push(`from ._pagination import ${pageNames.join(', ')}`);
|
|
231
|
+
}
|
|
232
|
+
const transportNames = ['Transport', ...['decode', 'join_csv'].filter((n) => ctx.transportImports.has(n))];
|
|
233
|
+
lines.push(`from ._transport import ${transportNames.join(', ')}`);
|
|
234
|
+
lines.push('from .models import * # noqa: F401,F403');
|
|
235
|
+
return `${lines.join('\n')}\n\n\n${classes.join('\n\n\n')}\n`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* The globally-unique resource class name, path-qualified by the FULL segment
|
|
240
|
+
* chain from root (mirrors the Go emitter's `serviceTypeName`). Two different
|
|
241
|
+
* `roles` resources under different parents (`projects.roles` vs
|
|
242
|
+
* `projects.groups.roles`) therefore get distinct class names
|
|
243
|
+
* (`ProjectsRolesResource` vs `ProjectsGroupsRolesResource`) instead of one
|
|
244
|
+
* shadowing the other in the single generated `resources.py` module. Attribute
|
|
245
|
+
* (field) names stay local (`self.roles`), like the Go emitter.
|
|
246
|
+
*/
|
|
247
|
+
function resourceClassName(segments: string[]): string {
|
|
248
|
+
return `${segments.map((s) => pascalCase(s)).join('')}Resource`;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function resourceClass(resource: Resource, segments: string[], ctx: ResourcesCtx): string {
|
|
252
|
+
const cls = resourceClassName(segments);
|
|
253
|
+
const subs = resource.resources || [];
|
|
254
|
+
const ctorLines = [' self._transport = transport'];
|
|
255
|
+
for (const sub of subs)
|
|
256
|
+
ctorLines.push(` self.${snakeCase(sub.name)} = ${resourceClassName([...segments, sub.name])}(transport)`);
|
|
257
|
+
const ctor = ` def __init__(self, transport: Transport) -> None:\n${ctorLines.join('\n')}`;
|
|
258
|
+
const methods = (resource.methods || []).map((m) => methodDef(m, ctx));
|
|
259
|
+
return `class ${cls}:\n${[ctor, ...methods].join('\n\n')}`;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function methodDef(method: Method, ctx: ResourcesCtx): string {
|
|
263
|
+
const plan = planOperation(method, ctx.types);
|
|
264
|
+
const name = snakeCase(method.action);
|
|
265
|
+
const { path: pathParams, query: queryParams, header: headerParams } = plan.paramGroups;
|
|
266
|
+
const rawContentType = plan.binaryContentType;
|
|
267
|
+
|
|
268
|
+
// Signature: positional path args, then keyword-only query/header/body params.
|
|
269
|
+
const positional = pathParams.map((p) => `${snakeCase(p.name)}: ${pyType(p.type, ctx.uses)}`);
|
|
270
|
+
const kwArgs: string[] = [];
|
|
271
|
+
for (const p of [...queryParams, ...headerParams]) kwArgs.push(paramArg(p, ctx));
|
|
272
|
+
const bodyParams = bodyFieldList(method, ctx.types);
|
|
273
|
+
for (const b of bodyParams) {
|
|
274
|
+
const type = pyType(b.type, ctx.uses);
|
|
275
|
+
kwArgs.push(
|
|
276
|
+
b.required ? `${snakeCase(b.name)}: ${type}` : `${snakeCase(b.name)}: ${optionalize(type, ctx.uses)} = None`,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
const params = ['self', ...positional, ...(kwArgs.length ? ['*', ...kwArgs] : [])].join(', ');
|
|
280
|
+
|
|
281
|
+
const httpMethod = method.httpMethod.toUpperCase();
|
|
282
|
+
const callArgs = [JSON.stringify(httpMethod), pathExpr(method.path, pathParams.length > 0)];
|
|
283
|
+
if (queryParams.length) {
|
|
284
|
+
callArgs.push(`query={${queryParams.map((q) => queryEntry(q, ctx)).join(', ')}}`);
|
|
285
|
+
}
|
|
286
|
+
if (bodyParams.length) {
|
|
287
|
+
const entries = bodyParams.map((b) => `${JSON.stringify(b.name)}: ${snakeCase(b.name)}`).join(', ');
|
|
288
|
+
callArgs.push(`body={${entries}}`);
|
|
289
|
+
}
|
|
290
|
+
// Header params go on the wire under their raw names; binary downloads also
|
|
291
|
+
// send an Accept header for the primary content type (user params win).
|
|
292
|
+
const headerEntries = headerParams.map((h) => `${JSON.stringify(h.wireName ?? h.name)}: ${snakeCase(h.name)}`);
|
|
293
|
+
if (rawContentType) headerEntries.unshift(`"Accept": ${JSON.stringify(rawContentType)}`);
|
|
294
|
+
if (headerEntries.length) callArgs.push(`headers={${headerEntries.join(', ')}}`);
|
|
295
|
+
// Body encoding: the IR encoding (json|multipart|form) normally decides, but a
|
|
296
|
+
// body that carries a binary field (bytes / file-like) must NOT be json.dumps'd
|
|
297
|
+
// even when the spec labels it application/json — some specs (e.g. OpenAI's
|
|
298
|
+
// `skills` upload) declare a json content type over a `format: binary` field.
|
|
299
|
+
// Route those through the multipart encoder, mirroring the Go apiform encoder.
|
|
300
|
+
let encoding = plan.encoding ?? 'json';
|
|
301
|
+
if (bodyParams.length && encoding === 'json' && bodyParams.some((b) => isBinaryTypeRef(b.type, ctx.types))) {
|
|
302
|
+
encoding = 'multipart';
|
|
303
|
+
}
|
|
304
|
+
if (bodyParams.length && encoding !== 'json') callArgs.push(`encoding=${JSON.stringify(encoding)}`);
|
|
305
|
+
if (rawContentType) callArgs.push('raw=True');
|
|
306
|
+
// sdk.idempotency: flagged methods get a transport-generated key (one per
|
|
307
|
+
// logical call, stable across retries) under the policy header name.
|
|
308
|
+
if (plan.injectIdempotencyKey && ctx.behavior.idempotency.autoGenerateForPost) {
|
|
309
|
+
callArgs.push('idempotency=True');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const call = `self._transport.request(${callArgs.join(', ')})`;
|
|
313
|
+
const { annotation, body } = returnPlan(plan, call, ctx);
|
|
314
|
+
const guards = pathParamGuards(pathParams);
|
|
315
|
+
const fullBody = guards ? `${guards}\n${body}` : body;
|
|
316
|
+
return ` def ${name}(${params}) -> ${annotation}:\n${fullBody}`;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Guard statements raised at the top of a method for each required string path
|
|
321
|
+
* param: reject the empty string BEFORE building the path (an empty segment
|
|
322
|
+
* would otherwise silently collapse `/pets/{id}` to the collection endpoint).
|
|
323
|
+
* Matches openai-python and the Go emitter's guard; the generated test suite's
|
|
324
|
+
* test_path_params_* variant asserts it fires.
|
|
325
|
+
*/
|
|
326
|
+
function pathParamGuards(pathParams: Param[]): string {
|
|
327
|
+
const lines: string[] = [];
|
|
328
|
+
for (const p of pathParams) {
|
|
329
|
+
if (p.type?.kind !== 'scalar' || p.type.scalar !== 'string' || p.required === false) continue;
|
|
330
|
+
const n = snakeCase(p.name);
|
|
331
|
+
lines.push(` if not ${n}:`);
|
|
332
|
+
lines.push(` raise ValueError(f"Expected a non-empty value for \`${n}\` but received {${n}!r}")`);
|
|
333
|
+
}
|
|
334
|
+
return lines.join('\n');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function paramArg(p: Param, ctx: ResourcesCtx): string {
|
|
338
|
+
const type = pyType(p.type, ctx.uses);
|
|
339
|
+
if (p.required) return `${snakeCase(p.name)}: ${type}`;
|
|
340
|
+
return `${snakeCase(p.name)}: ${optionalize(type, ctx.uses)} = None`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* One `wire-name: value` query entry. Exploded arrays are sent as repeated
|
|
345
|
+
* keys by the transport (urlencode doseq); explode=false arrays comma-join.
|
|
346
|
+
*/
|
|
347
|
+
function queryEntry(q: Param, ctx: ResourcesCtx): string {
|
|
348
|
+
const wire = JSON.stringify(q.wireName ?? q.name);
|
|
349
|
+
const value = snakeCase(q.name);
|
|
350
|
+
if (q.type?.kind === 'array' && q.explode === false) {
|
|
351
|
+
ctx.transportImports.add('join_csv');
|
|
352
|
+
return `${wire}: join_csv(${value})`;
|
|
353
|
+
}
|
|
354
|
+
return `${wire}: ${value}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** The return annotation plus the method body (indented statement lines). */
|
|
358
|
+
function returnPlan(plan: OperationPlan, call: string, ctx: ResourcesCtx): { annotation: string; body: string } {
|
|
359
|
+
const { method } = plan;
|
|
360
|
+
if (plan.binaryContentType) return { annotation: 'bytes', body: ` return ${call}` };
|
|
361
|
+
const page = pyPageName(plan);
|
|
362
|
+
if (page) {
|
|
363
|
+
ctx.pages.add(page);
|
|
364
|
+
const item = pyType(method.pagination?.itemType as TypeRef | undefined, ctx.uses);
|
|
365
|
+
return { annotation: `${page}[${item}]`, body: ` return ${page}.from_response(${item}, ${call})` };
|
|
366
|
+
}
|
|
367
|
+
const primary = method.primaryResponse as TypeRef | undefined;
|
|
368
|
+
if (!primary) return { annotation: 'None', body: ` ${call}` };
|
|
369
|
+
const type = pyType(primary, ctx.uses);
|
|
370
|
+
if (isPassthroughType(type)) return { annotation: type, body: ` return ${call}` };
|
|
371
|
+
ctx.transportImports.add('decode');
|
|
372
|
+
return { annotation: type, body: ` return decode(${type}, ${call})` };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
interface BodyField {
|
|
376
|
+
name: string;
|
|
377
|
+
type: TypeRef;
|
|
378
|
+
required: boolean;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Whether a TypeRef ultimately carries binary bytes (`format: binary`),
|
|
383
|
+
* following array items and named union/alias refs. Struct/enum refs are never
|
|
384
|
+
* binary. A `seen` set guards recursive/self-referential unions.
|
|
385
|
+
*/
|
|
386
|
+
function isBinaryTypeRef(ref: TypeRef | undefined, types: Map<string, NamedType>, seen = new Set<string>()): boolean {
|
|
387
|
+
if (!ref) return false;
|
|
388
|
+
if (ref.kind === 'scalar') return ref.scalar === 'string' && ref.format === 'binary';
|
|
389
|
+
if (ref.kind === 'array') return isBinaryTypeRef(ref.items as TypeRef | undefined, types, seen);
|
|
390
|
+
if (ref.kind === 'ref' && ref.name) {
|
|
391
|
+
if (seen.has(ref.name)) return false;
|
|
392
|
+
seen.add(ref.name);
|
|
393
|
+
const named = types.get(ref.name);
|
|
394
|
+
if (!named) return false;
|
|
395
|
+
if (named.kind === 'union') {
|
|
396
|
+
return (named.variants || []).some((v) => isBinaryTypeRef(v as TypeRef, types, seen));
|
|
397
|
+
}
|
|
398
|
+
if (named.kind === 'alias') return isBinaryTypeRef(named.of as TypeRef | undefined, types, seen);
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function bodyFieldList(method: Method, types: Map<string, NamedType>): BodyField[] {
|
|
404
|
+
const ref = method.requestBody?.type;
|
|
405
|
+
if (ref?.kind !== 'ref' || !ref.name) return [];
|
|
406
|
+
const named = types.get(ref.name);
|
|
407
|
+
return (named?.fields || []).map((f) => ({ name: f.name, type: f.type, required: f.required === true }));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function pathExpr(path: string, hasParams: boolean): string {
|
|
411
|
+
const p = path.startsWith('/') ? path : `/${path}`;
|
|
412
|
+
if (!hasParams) return JSON.stringify(p);
|
|
413
|
+
// Replace {wire} with {snake} and emit an f-string.
|
|
414
|
+
const fstr = p.replace(/\{([^}]+)\}/g, (_, name) => `{${snakeCase(name)}}`);
|
|
415
|
+
return `f${JSON.stringify(fstr)}`;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// ---- _client.py ----------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
export function clientPy(spec: OpensdkSpecJson, envVar: string): string {
|
|
421
|
+
const resources = spec.resources || [];
|
|
422
|
+
const attrLines = resources.map(
|
|
423
|
+
(r) => ` self.${snakeCase(r.name)} = ${resourceClassName([r.name])}(self._transport)`,
|
|
424
|
+
);
|
|
425
|
+
const imports = resources.map((r) => resourceClassName([r.name])).join(', ');
|
|
426
|
+
return `from __future__ import annotations
|
|
427
|
+
|
|
428
|
+
import os
|
|
429
|
+
from typing import Optional
|
|
430
|
+
|
|
431
|
+
from ._transport import Transport
|
|
432
|
+
from .resources import ${imports}
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
class Client:
|
|
436
|
+
def __init__(
|
|
437
|
+
self,
|
|
438
|
+
api_key: Optional[str] = None,
|
|
439
|
+
base_url: Optional[str] = None,
|
|
440
|
+
timeout: Optional[float] = None,
|
|
441
|
+
) -> None:
|
|
442
|
+
key = api_key if api_key is not None else os.environ.get(${JSON.stringify(envVar)})
|
|
443
|
+
self._transport = Transport(base_url=base_url, api_key=key, timeout=timeout)
|
|
444
|
+
${attrLines.join('\n')}
|
|
445
|
+
`;
|
|
446
|
+
}
|
package/src/publish.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type EmitterPublishOptions, runCommand } from '@xyd-js/opensdk-framework';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Publish the generated Python SDK to a PyPI-compatible index: `python -m build`
|
|
5
|
+
* (needs the PyPA `build` package) then `twine upload`. Auth via TWINE_* env; the
|
|
6
|
+
* token becomes TWINE_PASSWORD with the `__token__` username convention.
|
|
7
|
+
*/
|
|
8
|
+
export function publishPython(dir: string, opts: EmitterPublishOptions = {}): void {
|
|
9
|
+
runCommand('python3', ['-m', 'build'], { cwd: dir });
|
|
10
|
+
if (opts.dryRun) return;
|
|
11
|
+
const args = ['upload'];
|
|
12
|
+
if (opts.registry) args.push('--repository-url', opts.registry);
|
|
13
|
+
args.push('dist/*');
|
|
14
|
+
runCommand('twine', args, {
|
|
15
|
+
cwd: dir,
|
|
16
|
+
env: {
|
|
17
|
+
...process.env,
|
|
18
|
+
TWINE_USERNAME: process.env.TWINE_USERNAME ?? '__token__',
|
|
19
|
+
TWINE_PASSWORD: opts.token ?? process.env.TWINE_PASSWORD ?? 'opensdk',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}
|
package/src/pytype.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { TypeRef } from '@xyd-js/opensdk-core';
|
|
2
|
+
|
|
3
|
+
import { pascalCase } from './naming';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Records which `typing` names a rendered file actually uses so the generated
|
|
7
|
+
* import line stays minimal (mirrors the Go emitter's Imports tracker).
|
|
8
|
+
*/
|
|
9
|
+
export class PyUses {
|
|
10
|
+
private readonly typing = new Set<string>();
|
|
11
|
+
|
|
12
|
+
use(name: string): void {
|
|
13
|
+
this.typing.add(name);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** The `from typing import ...` line, or null when nothing is used. */
|
|
17
|
+
typingImport(): string | null {
|
|
18
|
+
if (this.typing.size === 0) return null;
|
|
19
|
+
const order = ['Any', 'BinaryIO', 'Optional', 'Union'];
|
|
20
|
+
return `from typing import ${order.filter((n) => this.typing.has(n)).join(', ')}`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Map an IR TypeRef to a Python type expression (PEP 585 builtin generics:
|
|
26
|
+
* list[T] / dict[str, T]). Every returned expression is ALSO a valid runtime
|
|
27
|
+
* value, so generated code can hand it to the transport's `decode()`.
|
|
28
|
+
*/
|
|
29
|
+
export function pyType(ref: TypeRef | undefined, uses: PyUses): string {
|
|
30
|
+
if (!ref) return anyType(uses);
|
|
31
|
+
const base = pyBase(ref, uses);
|
|
32
|
+
return ref.nullable ? optionalize(base, uses) : base;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function pyBase(ref: TypeRef, uses: PyUses): string {
|
|
36
|
+
switch (ref.kind) {
|
|
37
|
+
case 'scalar':
|
|
38
|
+
return pyScalar(ref.scalar, ref.format, uses);
|
|
39
|
+
case 'ref':
|
|
40
|
+
return ref.name ? pascalCase(ref.name) : anyType(uses);
|
|
41
|
+
case 'array':
|
|
42
|
+
return `list[${pyType(ref.items as TypeRef | undefined, uses)}]`;
|
|
43
|
+
case 'map':
|
|
44
|
+
return `dict[str, ${pyType(ref.values as TypeRef | undefined, uses)}]`;
|
|
45
|
+
default:
|
|
46
|
+
return anyType(uses);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function pyScalar(scalar: string | undefined, format: string | undefined, uses: PyUses): string {
|
|
51
|
+
switch (scalar) {
|
|
52
|
+
case 'string':
|
|
53
|
+
if (format === 'binary') {
|
|
54
|
+
// Upload fields accept raw bytes or an open file-like object.
|
|
55
|
+
uses.use('Union');
|
|
56
|
+
uses.use('BinaryIO');
|
|
57
|
+
return 'Union[bytes, BinaryIO]';
|
|
58
|
+
}
|
|
59
|
+
return 'str';
|
|
60
|
+
case 'integer':
|
|
61
|
+
return 'int';
|
|
62
|
+
case 'number':
|
|
63
|
+
return 'float';
|
|
64
|
+
case 'boolean':
|
|
65
|
+
return 'bool';
|
|
66
|
+
default:
|
|
67
|
+
return anyType(uses);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function anyType(uses: PyUses): string {
|
|
72
|
+
uses.use('Any');
|
|
73
|
+
return 'Any';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Wrap a type in Optional[...] unless it already is. */
|
|
77
|
+
export function optionalize(type: string, uses: PyUses): string {
|
|
78
|
+
if (type.startsWith('Optional[')) return type;
|
|
79
|
+
uses.use('Optional');
|
|
80
|
+
return `Optional[${type}]`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Type expressions `decode()` can't refine — methods return the raw JSON as-is. */
|
|
84
|
+
export function isPassthroughType(type: string): boolean {
|
|
85
|
+
return type === 'Any' || type === 'str' || type === 'int' || type === 'float' || type === 'bool';
|
|
86
|
+
}
|