@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/emitter.ts","../src/method.ts","../src/naming.ts","../src/project.ts","../src/pytype.ts","../src/runtime.ts","../src/tests-py.ts","../src/example-py.ts","../src/publish.ts","../src/index.ts"],"sourcesContent":["import { type NamedType, type OpensdkSpecJson, type Resource, walkMethods } from '@xyd-js/opensdk-core';\nimport type { Emitter, EmitterContext, GeneratedFile } from '@xyd-js/opensdk-framework';\nimport { generate, planOperation } from '@xyd-js/opensdk-framework';\n\nimport { pyPageName } from './method';\nimport { snakeCase } from './naming';\nimport { clientPy, modelsPy, pyproject, resolvePythonOptions, resourcesPy } from './project';\nimport { errorClassNames, paginationPy, transportPy } from './runtime';\nimport { resourceTestPy, testConftestPy, testUtilsPy } from './tests-py';\nimport type { OpensdkPythonOptions } from './types';\n\nconst resolve = (spec: OpensdkSpecJson, ctx: EmitterContext) =>\n resolvePythonOptions(spec, ctx.emitterOptions as OpensdkPythonOptions);\n\n/**\n * The Python emitter plugin: a minimal, dependency-free SDK (dataclasses,\n * enums, stdlib urllib transport). Pure capability methods over the IR.\n */\nexport const pythonEmitter: Emitter = {\n language: 'python',\n\n fileHeader(): string {\n return 'Code generated by opensdk. DO NOT EDIT.';\n },\n\n generateProject(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {\n const { pkg } = resolve(spec, ctx);\n // User-owned scaffold: never clobber an existing pyproject.toml on regen.\n return [{ path: 'pyproject.toml', content: pyproject(pkg, spec), writeMode: 'skipIfExists' }];\n },\n\n generateClient(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {\n const { pkg, envVar } = resolve(spec, ctx);\n // The public error surface: APIError plus the sdk.errors policy kinds.\n const errors = ['APIError', ...errorClassNames(spec)];\n const all = ['Client', ...errors].sort();\n const init = `from ._client import Client\\nfrom ._transport import ${errors.join(', ')}\\n\\n__all__ = [${all\n .map((n) => JSON.stringify(n))\n .join(', ')}]\\n`;\n return [\n { path: `${pkg}/__init__.py`, content: init },\n { path: `${pkg}/_client.py`, content: clientPy(spec, envVar) },\n ];\n },\n\n // models.py is emitted even for an empty symbol table: resources.py\n // star-imports it, so the module must always exist.\n generateTypes(_types: NamedType[], ctx: EmitterContext): GeneratedFile[] {\n const { pkg } = resolve(ctx.spec, ctx);\n return [{ path: `${pkg}/models.py`, content: modelsPy(ctx.spec) }];\n },\n\n generateResources(_resources: Resource[], ctx: EmitterContext): GeneratedFile[] {\n const { pkg } = resolve(ctx.spec, ctx);\n return [{ path: `${pkg}/resources.py`, content: resourcesPy(ctx.spec, ctx.types) }];\n },\n\n generateRuntime(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {\n const { pkg, baseURL } = resolve(spec, ctx);\n const files: GeneratedFile[] = [{ path: `${pkg}/_transport.py`, content: transportPy(spec, pkg, baseURL) }];\n // Emitted only when some list method returns a page — a spec with no\n // paginated endpoints gets no dead runtime code (mirrors the Go emitter).\n if (walkMethods(spec).some(({ method }) => pyPageName(planOperation(method, ctx.types)) !== null)) {\n files.push({ path: `${pkg}/_pagination.py`, content: paginationPy() });\n }\n return files;\n },\n\n // The SDK's own pytest suite (openai-python's tests/api_resources/*). SYNC\n // only — no async/raw/streaming client yet (follow-ups). Off via\n // emitterOptions.tests === false; default ON. One test file per top-level\n // resource plus the shared conftest fixture + assert_matches_type helper.\n generateTests(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {\n if ((ctx.emitterOptions as OpensdkPythonOptions).tests === false) return [];\n const { pkg } = resolve(spec, ctx);\n const resources = spec.resources || [];\n if (resources.length === 0) return [];\n const files: GeneratedFile[] = [\n { path: 'tests/utils.py', content: testUtilsPy() },\n { path: 'tests/conftest.py', content: testConftestPy(pkg) },\n ];\n for (const r of resources) {\n files.push({ path: `tests/test_${snakeCase(r.name)}.py`, content: resourceTestPy(r, pkg, ctx.types) });\n }\n return files;\n },\n};\n\n/**\n * Generate a minimal Python SDK from an OpenSDK IR. Back-compat wrapper:\n * drives the `pythonEmitter` plugin through the framework orchestrator.\n */\nexport function opensdkPython(spec: OpensdkSpecJson, options: OpensdkPythonOptions = {}): Record<string, string> {\n return generate(spec, pythonEmitter, options as Record<string, unknown>);\n}\n","import type { OperationPlan } from '@xyd-js/opensdk-framework';\n\n/**\n * The Python page container for a planned method. All \"what should this\n * method do\" derivations (binary content type, encoding, pagination gates,\n * idempotency) come from the framework's shared `planOperation()` — this\n * adapter only narrows the plan to what the Python runtime can render:\n * OffsetPage has no vendored Python container yet, so offset-style methods\n * keep the raw envelope return.\n */\nexport function pyPageName(plan: OperationPlan): 'CursorPage' | 'Page' | null {\n return plan.pageName === 'CursorPage' || plan.pageName === 'Page' ? plan.pageName : null;\n}\n","/** Split an identifier (camel/snake/kebab/space/dot) into lowercase words. */\nexport function splitWords(input: string): string[] {\n return input\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .split(/[^a-zA-Z0-9]+/) // split on ANY non-alphanumeric so wire junk (e.g. `ids[]`) can't leak into an identifier\n .map((w) => w.trim().toLowerCase())\n .filter(Boolean);\n}\n\n/** Prefix `_` when an identifier would start with a digit (illegal in Python). */\nfunction safeIdent(s: string): string {\n return /^[0-9]/.test(s) ? `_${s}` : s;\n}\n\n/** PascalCase, e.g. \"pet-list\" → \"PetList\". */\nexport function pascalCase(input: string): string {\n const s = splitWords(input)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('');\n return safeIdent(s);\n}\n\n/** snake_case (Python identifiers), e.g. \"petId\" → \"pet_id\". */\nexport function snakeCase(input: string): string {\n const s = safeIdent(splitWords(input).join('_'));\n return PY_KEYWORDS.has(s) ? `${s}_` : s;\n}\n\n/** A Python module/package name: snake_case, alphanumerics + underscore only. */\nexport function pyModuleName(input: string): string {\n const s = splitWords(input).join('_').replace(/[^a-z0-9_]/g, '');\n return s || 'client';\n}\n\n/** SCREAMING_SNAKE_CASE, e.g. \"petstore\" → \"PETSTORE\" (enum members: `_` prefix if digit-leading). */\nexport function screamingSnakeCase(input: string): string {\n return safeIdent(splitWords(input).join('_').toUpperCase().replace(/[^A-Z0-9_]/g, ''));\n}\n\nconst PY_KEYWORDS = new Set([\n 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif',\n 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda',\n 'none', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield',\n]);\n","import {\n type Field,\n type Method,\n type NamedType,\n type OpensdkSpecJson,\n type Param,\n type ResolvedSdkBehavior,\n type Resource,\n type TypeRef,\n sdkBehavior,\n} from '@xyd-js/opensdk-core';\nimport { type OperationPlan, planOperation } from '@xyd-js/opensdk-framework';\n\nimport { pyPageName } from './method';\nimport { pascalCase, pyModuleName, screamingSnakeCase, snakeCase } from './naming';\nimport { PyUses, isPassthroughType, optionalize, pyType } from './pytype';\nimport type { OpensdkPythonOptions } from './types';\n\n// Pure per-file renderers for the Python SDK — the second target (after Go),\n// proving the IR is language-agnostic. Dependency-free (stdlib urllib\n// transport in runtime.ts); mirrors the Go emitter's minimum bar: typed\n// signatures, decoded model returns, page containers, structured errors and\n// wire-correct query/form/multipart encoding. Driven by the emitter plugin in\n// emitter.ts; `opensdkPython()` there wraps it for back-compat.\n\nexport interface ResolvedPythonOptions {\n pkg: string;\n baseURL: string;\n envVar: string;\n}\n\nexport function resolvePythonOptions(spec: OpensdkSpecJson, options: OpensdkPythonOptions): ResolvedPythonOptions {\n const pkg = options.packageName ?? pyModuleName(spec.info.title);\n return {\n pkg,\n baseURL: options.baseURL ?? spec.servers?.[0] ?? '',\n envVar: spec.security?.find((s) => s.envVar)?.envVar ?? `${screamingSnakeCase(pkg)}_API_KEY`,\n };\n}\n\n/**\n * The generated `pyproject.toml`: a PEP 621 project table with a `[build-system]`\n * so `python -m build` produces an installable/publishable wheel + sdist. Publish\n * identity (description/authors/license/urls) comes from `spec.info` — the OpenAPI\n * `info` or an sdk.json `publish` override. Dependency-free (stdlib transport).\n */\nexport function pyproject(pkg: string, spec: OpensdkSpecJson): string {\n const info = spec.info;\n const lines = [\n '[build-system]',\n 'requires = [\"setuptools>=61\"]',\n 'build-backend = \"setuptools.build_meta\"',\n '',\n '[project]',\n `name = ${JSON.stringify(pkg.replace(/_/g, '-'))}`,\n `version = ${JSON.stringify(info.version || '0.0.0')}`,\n ];\n if (info.description) lines.push(`description = ${JSON.stringify(info.description)}`);\n lines.push('requires-python = \">=3.9\"');\n if (info.contact?.name) lines.push(`authors = [{ name = ${JSON.stringify(info.contact.name)} }]`);\n if (info.license?.identifier) lines.push(`license = { text = ${JSON.stringify(info.license.identifier)} }`);\n const urls: string[] = [];\n if (info.homepage) urls.push(`Homepage = ${JSON.stringify(info.homepage)}`);\n if (info.repository) urls.push(`Repository = ${JSON.stringify(info.repository)}`);\n if (urls.length) lines.push('', '[project.urls]', ...urls);\n lines.push('', '[tool.setuptools.packages.find]', `include = [${JSON.stringify(pkg)}]`);\n return `${lines.join('\\n')}\\n`;\n}\n\n// ---- models.py -----------------------------------------------------------\n\ninterface ModelsCtx {\n uses: PyUses;\n needsField: boolean;\n}\n\nexport function modelsPy(spec: OpensdkSpecJson): string {\n const ctx: ModelsCtx = { uses: new PyUses(), needsField: false };\n // Ordering matters: a struct's field annotations are lazy (`from __future__\n // import annotations`), so structs/enums may appear in any order. But an\n // alias/union assignment `X = list[Y]` is evaluated EAGERLY at import, so Y\n // must already be defined. Emit all structs/enums first, then the alias group\n // topologically sorted so an alias that references another alias comes after it.\n const types = spec.types || [];\n const aliasKinds = new Set(['alias', 'union']);\n const structsEnums = types.filter((t) => !aliasKinds.has(t.kind));\n const aliases = orderAliases(types.filter((t) => aliasKinds.has(t.kind)));\n const decls = [...structsEnums, ...aliases].map((t) => namedType(t, ctx)).filter(Boolean);\n const lines = [\n 'from __future__ import annotations',\n '',\n `from dataclasses import dataclass${ctx.needsField ? ', field' : ''}`,\n 'from enum import Enum',\n ];\n const typingLine = ctx.uses.typingImport();\n if (typingLine) lines.push(typingLine);\n return `${lines.join('\\n')}\\n\\n\\n${decls.join('\\n\\n\\n')}\\n`;\n}\n\n/** All named-type references inside a TypeRef tree (for alias dependency ordering). */\nfunction typeRefNames(ref: TypeRef | undefined, out: Set<string>): void {\n if (!ref) return;\n if (ref.kind === 'ref' && ref.name) out.add(ref.name);\n typeRefNames(ref.items as TypeRef | undefined, out);\n typeRefNames(ref.values as TypeRef | undefined, out);\n}\n\n/**\n * Topologically order the alias/union group so an alias whose RHS references\n * another alias is emitted after it (the RHS is eagerly evaluated at import).\n * References to structs/enums are ignored (already emitted above); cycles fall\n * back to input order (unreachable for list/dict/Any alias forms).\n */\nfunction orderAliases(aliases: NamedType[]): NamedType[] {\n const byName = new Map(aliases.map((a) => [a.name, a]));\n const ordered: NamedType[] = [];\n const done = new Set<string>();\n const visiting = new Set<string>();\n const visit = (a: NamedType) => {\n if (done.has(a.name) || visiting.has(a.name)) return;\n visiting.add(a.name);\n const refs = new Set<string>();\n if (a.kind === 'alias') typeRefNames(a.of as TypeRef | undefined, refs);\n for (const r of refs) {\n const dep = byName.get(r);\n if (dep && dep !== a) visit(dep);\n }\n visiting.delete(a.name);\n done.add(a.name);\n ordered.push(a);\n };\n for (const a of aliases) visit(a);\n return ordered;\n}\n\nfunction namedType(type: NamedType, ctx: ModelsCtx): string {\n switch (type.kind) {\n case 'enum':\n return enumType(type);\n case 'alias':\n return `${pascalCase(type.name)} = ${pyType(type.of, ctx.uses)}`;\n case 'union':\n ctx.uses.use('Any');\n return `${pascalCase(type.name)} = Any`;\n default:\n return structType(type, ctx);\n }\n}\n\nfunction structType(type: NamedType, ctx: ModelsCtx): string {\n const name = pascalCase(type.name);\n const fields = type.fields || [];\n if (fields.length === 0) return `@dataclass\\nclass ${name}:\\n pass`;\n // Required fields first (no default), then optional (Optional[...] = None).\n const required = fields.filter((f) => f.required);\n const optional = fields.filter((f) => !f.required);\n const lines = [...required, ...optional].map((f) => structFieldLine(f, ctx));\n return `@dataclass\\nclass ${name}:\\n${lines.join('\\n')}`;\n}\n\n/**\n * One dataclass field. When the Python name differs from the wire name the\n * raw name is kept in `field(metadata={\"wire\": ...})` so the runtime's\n * encode/decode stay wire-correct.\n */\nfunction structFieldLine(f: Field, ctx: ModelsCtx): string {\n const py = snakeCase(f.name);\n const type = pyType(f.type, ctx.uses);\n const wire = py === f.name ? null : `metadata={\"wire\": ${JSON.stringify(f.name)}}`;\n if (f.required) {\n if (!wire) return ` ${py}: ${type}`;\n ctx.needsField = true;\n return ` ${py}: ${type} = field(${wire})`;\n }\n const opt = optionalize(type, ctx.uses);\n if (!wire) return ` ${py}: ${opt} = None`;\n ctx.needsField = true;\n return ` ${py}: ${opt} = field(default=None, ${wire})`;\n}\n\nfunction enumType(type: NamedType): string {\n const name = pascalCase(type.name);\n const base = type.base === 'integer' ? 'int' : 'str';\n const values = type.values || [];\n if (values.length === 0) return `class ${name}(${base}, Enum):\\n pass`;\n const members = values.map((v) => {\n const member = screamingSnakeCase(String(v.name ?? v.value)) || 'VALUE';\n const lit = base === 'int' ? String(v.value) : JSON.stringify(String(v.value));\n return ` ${member} = ${lit}`;\n });\n return `class ${name}(${base}, Enum):\\n${members.join('\\n')}`;\n}\n\n// ---- resources.py --------------------------------------------------------\n\ninterface ResourcesCtx {\n types: Map<string, NamedType>;\n /** The resolved runtime-behavior policies (sdk block over canonical defaults). */\n behavior: ResolvedSdkBehavior;\n uses: PyUses;\n /** Extra names imported from ._transport (decode, join_csv). */\n transportImports: Set<string>;\n /** Page containers imported from ._pagination. */\n pages: Set<'CursorPage' | 'Page'>;\n}\n\nexport function resourcesPy(spec: OpensdkSpecJson, types: Map<string, NamedType>): string {\n const ctx: ResourcesCtx = {\n types,\n behavior: sdkBehavior(spec),\n uses: new PyUses(),\n transportImports: new Set(),\n pages: new Set(),\n };\n const classes: string[] = [];\n const emit = (resources: Resource[], parent: string[]) => {\n for (const r of resources) {\n const segments = [...parent, r.name];\n classes.push(resourceClass(r, segments, ctx));\n if (r.resources?.length) emit(r.resources, segments);\n }\n };\n emit(spec.resources || [], []);\n\n const lines = ['from __future__ import annotations', ''];\n const typingLine = ctx.uses.typingImport();\n if (typingLine) lines.push(typingLine, '');\n if (ctx.pages.size > 0) {\n const pageNames = (['CursorPage', 'Page'] as const).filter((n) => ctx.pages.has(n));\n lines.push(`from ._pagination import ${pageNames.join(', ')}`);\n }\n const transportNames = ['Transport', ...['decode', 'join_csv'].filter((n) => ctx.transportImports.has(n))];\n lines.push(`from ._transport import ${transportNames.join(', ')}`);\n lines.push('from .models import * # noqa: F401,F403');\n return `${lines.join('\\n')}\\n\\n\\n${classes.join('\\n\\n\\n')}\\n`;\n}\n\n/**\n * The globally-unique resource class name, path-qualified by the FULL segment\n * chain from root (mirrors the Go emitter's `serviceTypeName`). Two different\n * `roles` resources under different parents (`projects.roles` vs\n * `projects.groups.roles`) therefore get distinct class names\n * (`ProjectsRolesResource` vs `ProjectsGroupsRolesResource`) instead of one\n * shadowing the other in the single generated `resources.py` module. Attribute\n * (field) names stay local (`self.roles`), like the Go emitter.\n */\nfunction resourceClassName(segments: string[]): string {\n return `${segments.map((s) => pascalCase(s)).join('')}Resource`;\n}\n\nfunction resourceClass(resource: Resource, segments: string[], ctx: ResourcesCtx): string {\n const cls = resourceClassName(segments);\n const subs = resource.resources || [];\n const ctorLines = [' self._transport = transport'];\n for (const sub of subs)\n ctorLines.push(` self.${snakeCase(sub.name)} = ${resourceClassName([...segments, sub.name])}(transport)`);\n const ctor = ` def __init__(self, transport: Transport) -> None:\\n${ctorLines.join('\\n')}`;\n const methods = (resource.methods || []).map((m) => methodDef(m, ctx));\n return `class ${cls}:\\n${[ctor, ...methods].join('\\n\\n')}`;\n}\n\nfunction methodDef(method: Method, ctx: ResourcesCtx): string {\n const plan = planOperation(method, ctx.types);\n const name = snakeCase(method.action);\n const { path: pathParams, query: queryParams, header: headerParams } = plan.paramGroups;\n const rawContentType = plan.binaryContentType;\n\n // Signature: positional path args, then keyword-only query/header/body params.\n const positional = pathParams.map((p) => `${snakeCase(p.name)}: ${pyType(p.type, ctx.uses)}`);\n const kwArgs: string[] = [];\n for (const p of [...queryParams, ...headerParams]) kwArgs.push(paramArg(p, ctx));\n const bodyParams = bodyFieldList(method, ctx.types);\n for (const b of bodyParams) {\n const type = pyType(b.type, ctx.uses);\n kwArgs.push(\n b.required ? `${snakeCase(b.name)}: ${type}` : `${snakeCase(b.name)}: ${optionalize(type, ctx.uses)} = None`,\n );\n }\n const params = ['self', ...positional, ...(kwArgs.length ? ['*', ...kwArgs] : [])].join(', ');\n\n const httpMethod = method.httpMethod.toUpperCase();\n const callArgs = [JSON.stringify(httpMethod), pathExpr(method.path, pathParams.length > 0)];\n if (queryParams.length) {\n callArgs.push(`query={${queryParams.map((q) => queryEntry(q, ctx)).join(', ')}}`);\n }\n if (bodyParams.length) {\n const entries = bodyParams.map((b) => `${JSON.stringify(b.name)}: ${snakeCase(b.name)}`).join(', ');\n callArgs.push(`body={${entries}}`);\n }\n // Header params go on the wire under their raw names; binary downloads also\n // send an Accept header for the primary content type (user params win).\n const headerEntries = headerParams.map((h) => `${JSON.stringify(h.wireName ?? h.name)}: ${snakeCase(h.name)}`);\n if (rawContentType) headerEntries.unshift(`\"Accept\": ${JSON.stringify(rawContentType)}`);\n if (headerEntries.length) callArgs.push(`headers={${headerEntries.join(', ')}}`);\n // Body encoding: the IR encoding (json|multipart|form) normally decides, but a\n // body that carries a binary field (bytes / file-like) must NOT be json.dumps'd\n // even when the spec labels it application/json — some specs (e.g. OpenAI's\n // `skills` upload) declare a json content type over a `format: binary` field.\n // Route those through the multipart encoder, mirroring the Go apiform encoder.\n let encoding = plan.encoding ?? 'json';\n if (bodyParams.length && encoding === 'json' && bodyParams.some((b) => isBinaryTypeRef(b.type, ctx.types))) {\n encoding = 'multipart';\n }\n if (bodyParams.length && encoding !== 'json') callArgs.push(`encoding=${JSON.stringify(encoding)}`);\n if (rawContentType) callArgs.push('raw=True');\n // sdk.idempotency: flagged methods get a transport-generated key (one per\n // logical call, stable across retries) under the policy header name.\n if (plan.injectIdempotencyKey && ctx.behavior.idempotency.autoGenerateForPost) {\n callArgs.push('idempotency=True');\n }\n\n const call = `self._transport.request(${callArgs.join(', ')})`;\n const { annotation, body } = returnPlan(plan, call, ctx);\n const guards = pathParamGuards(pathParams);\n const fullBody = guards ? `${guards}\\n${body}` : body;\n return ` def ${name}(${params}) -> ${annotation}:\\n${fullBody}`;\n}\n\n/**\n * Guard statements raised at the top of a method for each required string path\n * param: reject the empty string BEFORE building the path (an empty segment\n * would otherwise silently collapse `/pets/{id}` to the collection endpoint).\n * Matches openai-python and the Go emitter's guard; the generated test suite's\n * test_path_params_* variant asserts it fires.\n */\nfunction pathParamGuards(pathParams: Param[]): string {\n const lines: string[] = [];\n for (const p of pathParams) {\n if (p.type?.kind !== 'scalar' || p.type.scalar !== 'string' || p.required === false) continue;\n const n = snakeCase(p.name);\n lines.push(` if not ${n}:`);\n lines.push(` raise ValueError(f\"Expected a non-empty value for \\`${n}\\` but received {${n}!r}\")`);\n }\n return lines.join('\\n');\n}\n\nfunction paramArg(p: Param, ctx: ResourcesCtx): string {\n const type = pyType(p.type, ctx.uses);\n if (p.required) return `${snakeCase(p.name)}: ${type}`;\n return `${snakeCase(p.name)}: ${optionalize(type, ctx.uses)} = None`;\n}\n\n/**\n * One `wire-name: value` query entry. Exploded arrays are sent as repeated\n * keys by the transport (urlencode doseq); explode=false arrays comma-join.\n */\nfunction queryEntry(q: Param, ctx: ResourcesCtx): string {\n const wire = JSON.stringify(q.wireName ?? q.name);\n const value = snakeCase(q.name);\n if (q.type?.kind === 'array' && q.explode === false) {\n ctx.transportImports.add('join_csv');\n return `${wire}: join_csv(${value})`;\n }\n return `${wire}: ${value}`;\n}\n\n/** The return annotation plus the method body (indented statement lines). */\nfunction returnPlan(plan: OperationPlan, call: string, ctx: ResourcesCtx): { annotation: string; body: string } {\n const { method } = plan;\n if (plan.binaryContentType) return { annotation: 'bytes', body: ` return ${call}` };\n const page = pyPageName(plan);\n if (page) {\n ctx.pages.add(page);\n const item = pyType(method.pagination?.itemType as TypeRef | undefined, ctx.uses);\n return { annotation: `${page}[${item}]`, body: ` return ${page}.from_response(${item}, ${call})` };\n }\n const primary = method.primaryResponse as TypeRef | undefined;\n if (!primary) return { annotation: 'None', body: ` ${call}` };\n const type = pyType(primary, ctx.uses);\n if (isPassthroughType(type)) return { annotation: type, body: ` return ${call}` };\n ctx.transportImports.add('decode');\n return { annotation: type, body: ` return decode(${type}, ${call})` };\n}\n\ninterface BodyField {\n name: string;\n type: TypeRef;\n required: boolean;\n}\n\n/**\n * Whether a TypeRef ultimately carries binary bytes (`format: binary`),\n * following array items and named union/alias refs. Struct/enum refs are never\n * binary. A `seen` set guards recursive/self-referential unions.\n */\nfunction isBinaryTypeRef(ref: TypeRef | undefined, types: Map<string, NamedType>, seen = new Set<string>()): boolean {\n if (!ref) return false;\n if (ref.kind === 'scalar') return ref.scalar === 'string' && ref.format === 'binary';\n if (ref.kind === 'array') return isBinaryTypeRef(ref.items as TypeRef | undefined, types, seen);\n if (ref.kind === 'ref' && ref.name) {\n if (seen.has(ref.name)) return false;\n seen.add(ref.name);\n const named = types.get(ref.name);\n if (!named) return false;\n if (named.kind === 'union') {\n return (named.variants || []).some((v) => isBinaryTypeRef(v as TypeRef, types, seen));\n }\n if (named.kind === 'alias') return isBinaryTypeRef(named.of as TypeRef | undefined, types, seen);\n }\n return false;\n}\n\nfunction bodyFieldList(method: Method, types: Map<string, NamedType>): BodyField[] {\n const ref = method.requestBody?.type;\n if (ref?.kind !== 'ref' || !ref.name) return [];\n const named = types.get(ref.name);\n return (named?.fields || []).map((f) => ({ name: f.name, type: f.type, required: f.required === true }));\n}\n\nfunction pathExpr(path: string, hasParams: boolean): string {\n const p = path.startsWith('/') ? path : `/${path}`;\n if (!hasParams) return JSON.stringify(p);\n // Replace {wire} with {snake} and emit an f-string.\n const fstr = p.replace(/\\{([^}]+)\\}/g, (_, name) => `{${snakeCase(name)}}`);\n return `f${JSON.stringify(fstr)}`;\n}\n\n// ---- _client.py ----------------------------------------------------------\n\nexport function clientPy(spec: OpensdkSpecJson, envVar: string): string {\n const resources = spec.resources || [];\n const attrLines = resources.map(\n (r) => ` self.${snakeCase(r.name)} = ${resourceClassName([r.name])}(self._transport)`,\n );\n const imports = resources.map((r) => resourceClassName([r.name])).join(', ');\n return `from __future__ import annotations\n\nimport os\nfrom typing import Optional\n\nfrom ._transport import Transport\nfrom .resources import ${imports}\n\n\nclass Client:\n def __init__(\n self,\n api_key: Optional[str] = None,\n base_url: Optional[str] = None,\n timeout: Optional[float] = None,\n ) -> None:\n key = api_key if api_key is not None else os.environ.get(${JSON.stringify(envVar)})\n self._transport = Transport(base_url=base_url, api_key=key, timeout=timeout)\n${attrLines.join('\\n')}\n`;\n}\n","import type { TypeRef } from '@xyd-js/opensdk-core';\n\nimport { pascalCase } from './naming';\n\n/**\n * Records which `typing` names a rendered file actually uses so the generated\n * import line stays minimal (mirrors the Go emitter's Imports tracker).\n */\nexport class PyUses {\n private readonly typing = new Set<string>();\n\n use(name: string): void {\n this.typing.add(name);\n }\n\n /** The `from typing import ...` line, or null when nothing is used. */\n typingImport(): string | null {\n if (this.typing.size === 0) return null;\n const order = ['Any', 'BinaryIO', 'Optional', 'Union'];\n return `from typing import ${order.filter((n) => this.typing.has(n)).join(', ')}`;\n }\n}\n\n/**\n * Map an IR TypeRef to a Python type expression (PEP 585 builtin generics:\n * list[T] / dict[str, T]). Every returned expression is ALSO a valid runtime\n * value, so generated code can hand it to the transport's `decode()`.\n */\nexport function pyType(ref: TypeRef | undefined, uses: PyUses): string {\n if (!ref) return anyType(uses);\n const base = pyBase(ref, uses);\n return ref.nullable ? optionalize(base, uses) : base;\n}\n\nfunction pyBase(ref: TypeRef, uses: PyUses): string {\n switch (ref.kind) {\n case 'scalar':\n return pyScalar(ref.scalar, ref.format, uses);\n case 'ref':\n return ref.name ? pascalCase(ref.name) : anyType(uses);\n case 'array':\n return `list[${pyType(ref.items as TypeRef | undefined, uses)}]`;\n case 'map':\n return `dict[str, ${pyType(ref.values as TypeRef | undefined, uses)}]`;\n default:\n return anyType(uses);\n }\n}\n\nfunction pyScalar(scalar: string | undefined, format: string | undefined, uses: PyUses): string {\n switch (scalar) {\n case 'string':\n if (format === 'binary') {\n // Upload fields accept raw bytes or an open file-like object.\n uses.use('Union');\n uses.use('BinaryIO');\n return 'Union[bytes, BinaryIO]';\n }\n return 'str';\n case 'integer':\n return 'int';\n case 'number':\n return 'float';\n case 'boolean':\n return 'bool';\n default:\n return anyType(uses);\n }\n}\n\nfunction anyType(uses: PyUses): string {\n uses.use('Any');\n return 'Any';\n}\n\n/** Wrap a type in Optional[...] unless it already is. */\nexport function optionalize(type: string, uses: PyUses): string {\n if (type.startsWith('Optional[')) return type;\n uses.use('Optional');\n return `Optional[${type}]`;\n}\n\n/** Type expressions `decode()` can't refine — methods return the raw JSON as-is. */\nexport function isPassthroughType(type: string): boolean {\n return type === 'Any' || type === 'str' || type === 'int' || type === 'float' || type === 'bool';\n}\n","import { type OpensdkSpecJson, type ResolvedSdkBehavior, sdkBehavior } from '@xyd-js/opensdk-core';\n\n// The generated Python runtime, mirroring the Go emitter's vendored runtime at\n// its minimum bar: a stdlib-only transport (urllib) with structured APIError,\n// wire-correct query/form/multipart encoding, best-effort typed decode into\n// the generated dataclasses, and (only when a method pages) generic\n// CursorPage/Page containers.\n//\n// Runtime BEHAVIOR (retry loop, timeout, User-Agent, error kinds, request\n// guard, idempotency) is policy-driven: every constant below is interpolated\n// from the IR's `sdk` block via opensdk-core's `sdkBehavior(spec)`, so the\n// Python and Go runtimes encode the same declared values instead of drifting.\n\n// ---- Python literal helpers ------------------------------------------------\n\nfunction pyStr(value: string): string {\n return JSON.stringify(value);\n}\n\nfunction pyBool(value: boolean): string {\n return value ? 'True' : 'False';\n}\n\n/** A float literal (Python): integers render as `60.0` so units read as seconds. */\nfunction pyFloat(value: number): string {\n return Number.isInteger(value) ? `${value}.0` : String(value);\n}\n\nfunction pyFrozenset(items: string[]): string {\n return items.length ? `frozenset({${items.join(', ')}})` : 'frozenset()';\n}\n\nfunction pyStrDict(record: Record<string, string>): string {\n const entries = Object.entries(record).map(([key, value]) => `${pyStr(key)}: ${pyStr(value)}`);\n return `{${entries.join(', ')}}`;\n}\n\n// ---- error-kind classes (sdk.errors) --------------------------------------\n\n/**\n * The Python exception class for a policy error kind: `NotFound` ->\n * `NotFoundError`; the canonical client kind `API` IS the `APIError` base.\n */\nfunction errorClassName(kind: string): string {\n if (kind === 'API') return 'APIError';\n return kind.endsWith('Error') ? kind : `${kind}Error`;\n}\n\n/**\n * The generated `APIError` subclass names (sorted), for the package\n * `__init__` exports. `APIError` itself is not included.\n */\nexport function errorClassNames(spec: OpensdkSpecJson): string[] {\n const behavior = sdkBehavior(spec);\n const names = new Set<string>();\n for (const kind of Object.values(behavior.errors.statusCodeMap)) names.add(errorClassName(kind));\n names.add(errorClassName(behavior.errors.serverErrorKind));\n names.add(errorClassName(behavior.errors.clientErrorKind));\n names.delete('APIError');\n return [...names].sort();\n}\n\n/** The per-kind exception classes plus the status -> class dispatch table. */\nfunction errorClassesBlock(behavior: ResolvedSdkBehavior): string {\n const mapped = Object.entries(behavior.errors.statusCodeMap)\n .map(([status, kind]) => [Number(status), kind] as const)\n .sort((a, b) => a[0] - b[0]);\n\n // Class -> its policy kind + the statuses it maps (several statuses may share a kind).\n const byClass = new Map<string, { kind: string; statuses: number[] }>();\n for (const [status, kind] of mapped) {\n const cls = errorClassName(kind);\n if (cls === 'APIError') continue;\n const entry = byClass.get(cls) || { kind, statuses: [] };\n entry.statuses.push(status);\n byClass.set(cls, entry);\n }\n\n const serverClass = errorClassName(behavior.errors.serverErrorKind);\n const clientClass = errorClassName(behavior.errors.clientErrorKind);\n\n const errorClass = (cls: string, kind: string, doc: string): string =>\n `class ${cls}(APIError):\\n \"\"\"${doc}\"\"\"\\n\\n kind = ${pyStr(kind)}`;\n\n const classes: string[] = [];\n for (const [cls, { kind, statuses }] of byClass) {\n classes.push(errorClass(cls, kind, `The mapped error kind for HTTP ${statuses.join('/')} responses.`));\n }\n if (serverClass !== 'APIError' && !byClass.has(serverClass)) {\n classes.push(errorClass(serverClass, behavior.errors.serverErrorKind, 'Catch-all for unmapped 5xx responses.'));\n }\n if (clientClass !== 'APIError' && !byClass.has(clientClass) && clientClass !== serverClass) {\n classes.push(\n errorClass(clientClass, behavior.errors.clientErrorKind, 'Catch-all for unmapped non-5xx error responses.'),\n );\n }\n\n const tableEntries = mapped.map(([status, kind]) => ` ${status}: ${errorClassName(kind)},`);\n const table = tableEntries.length\n ? `_STATUS_TO_ERROR: dict[int, type] = {\\n${tableEntries.join('\\n')}\\n}`\n : '_STATUS_TO_ERROR: dict[int, type] = {}';\n\n return `${classes.join('\\n\\n\\n')}\\n\\n\\n${table}\n\n\ndef _error_for_status(status_code: int, headers: dict[str, str], body: bytes) -> APIError:\n \"\"\"The policy-mapped exception: exact status map first, then the 5xx catch-all, then the client catch-all.\"\"\"\n cls = _STATUS_TO_ERROR.get(status_code)\n if cls is None:\n cls = ${serverClass} if status_code >= 500 else ${clientClass}\n return cls(status_code, headers, body)`;\n}\n\n// ---- _transport.py (auth + behavior policies baked from the spec) ----------\n\nexport function transportPy(spec: OpensdkSpecJson, pkg: string, baseURL: string): string {\n const behavior = sdkBehavior(spec);\n\n const security = spec.security?.[0];\n let authLine = '';\n if (security) {\n const name = security.name || '';\n switch (security.kind) {\n case 'apiKey-header':\n authLine = ` request_headers[${JSON.stringify(name)}] = self.api_key\\n`;\n break;\n case 'apiKey-query':\n authLine = ` params[${JSON.stringify(name)}] = self.api_key\\n`;\n break;\n default:\n authLine = ` request_headers[\"Authorization\"] = \"Bearer \" + self.api_key\\n`;\n }\n }\n const authBlock = authLine ? ` if self.api_key:\\n${authLine}` : '';\n\n // sdk.userAgent: the identifier is assembled at generation time from the\n // template; the runtime-version suffix and AI-agent sniff run at runtime.\n const userAgent = behavior.userAgent.sdkIdentifierTemplate\n .replace(/\\{package\\}/g, pkg)\n .replace(/\\{language\\}/g, 'python')\n .replace(/\\{version\\}/g, spec.info.version || '0.0.0');\n\n // sdk.timeout: milliseconds in the IR, seconds on urlopen; 0 = no deadline.\n const timeoutMs = behavior.timeout.defaultTimeoutMs;\n const defaultTimeout = timeoutMs > 0 ? pyFloat(timeoutMs / 1000) : 'None';\n const timeoutEnvVar = behavior.timeout.timeoutEnvVar;\n\n const retry = behavior.retry;\n const errorDocUrlTemplate = behavior.errors.errorDocUrlTemplate;\n const includeRuntimeVersion = behavior.userAgent.includeRuntimeVersion;\n\n const constants = [\n `DEFAULT_BASE_URL = ${pyStr(baseURL)}`,\n `USER_AGENT = ${pyStr(userAgent)}`,\n `AI_AGENT_ENV_VARS = ${pyStrDict(behavior.userAgent.aiAgentEnvVars)}`,\n `DEFAULT_TIMEOUT: Optional[float] = ${defaultTimeout}`,\n ...(timeoutEnvVar ? [`TIMEOUT_ENV_VAR = ${pyStr(timeoutEnvVar)}`] : []),\n `MAX_RETRIES = ${retry.maxRetries}`,\n `RETRYABLE_STATUS_CODES = ${pyFrozenset(retry.retryableStatusCodes.map(String))}`,\n `RETRY_CONNECTION_ERRORS = ${pyBool(retry.retryConnectionErrors)}`,\n `HONOR_RETRY_AFTER_HEADER = ${pyBool(retry.honorRetryAfterHeader)}`,\n `BACKOFF_INITIAL_DELAY = ${pyFloat(retry.backoff.initialDelayMs / 1000)}`,\n `BACKOFF_MAX_DELAY = ${pyFloat(retry.backoff.maxDelayMs / 1000)}`,\n `BACKOFF_MULTIPLIER = ${pyFloat(retry.backoff.multiplier)}`,\n `BACKOFF_JITTER = ${pyFloat(retry.backoff.jitter)}`,\n `REQUEST_ID_HEADER = ${pyStr(behavior.telemetry.requestIdHeader)}`,\n `IDEMPOTENCY_HEADER = ${pyStr(behavior.idempotency.headerName)}`,\n ...(errorDocUrlTemplate ? [`ERROR_DOC_URL_TEMPLATE = ${pyStr(errorDocUrlTemplate)}`] : []),\n `GUARDED_OPTION_KEYS = ${pyFrozenset(behavior.requestGuard.optionKeys.map(pyStr))}`,\n ].join('\\n');\n\n // sdk.errors.errorDocUrlTemplate ({kind}/{status} placeholders) is appended\n // to the error's string form only when the policy declares it.\n const errorDocStr = errorDocUrlTemplate\n ? `\n\n def __str__(self) -> str:\n url = ERROR_DOC_URL_TEMPLATE.replace(\"{kind}\", self.kind).replace(\"{status}\", str(self.status_code))\n return self.message + \" (\" + url + \")\"`\n : '';\n\n const runtimeVersionLine = includeRuntimeVersion ? '\\n ua += \" python/\" + platform.python_version()' : '';\n\n return `from __future__ import annotations\n\nimport dataclasses\nimport datetime\nimport email.utils\nimport json\nimport os${includeRuntimeVersion ? '\\nimport platform' : ''}\nimport random\nimport time\nimport typing\nimport urllib.error\nimport urllib.parse\nimport urllib.request\nimport uuid\nfrom enum import Enum\nfrom typing import Any, Optional\n\n${constants}\n\n\nclass APIError(Exception):\n \"\"\"A non-2xx API response: status code, headers, raw body, request id and a best-effort message.\"\"\"\n\n kind = \"API\"\n\n def __init__(self, status_code: int, headers: dict[str, str], body: bytes) -> None:\n self.status_code = status_code\n self.headers = headers\n self.body = body\n self.request_id = _header(headers, REQUEST_ID_HEADER)\n self.message = _error_message(body) or \"HTTP \" + str(status_code)\n super().__init__(self.message)${errorDocStr}\n\n\n${errorClassesBlock(behavior)}\n\n\ndef _error_message(body: bytes) -> Optional[str]:\n \"\"\"Best-effort message from a JSON error envelope ({\"error\": {\"message\": ...}} etc.).\"\"\"\n try:\n payload = json.loads(body.decode(\"utf-8\"))\n except Exception:\n return None\n if not isinstance(payload, dict):\n return None\n error = payload.get(\"error\")\n if isinstance(error, dict) and isinstance(error.get(\"message\"), str):\n return error[\"message\"]\n if isinstance(error, str):\n return error\n for key in (\"message\", \"detail\"):\n if isinstance(payload.get(key), str):\n return payload[key]\n return None\n\n\ndef _header(headers: dict[str, str], name: str) -> Optional[str]:\n \"\"\"Case-insensitive header lookup.\"\"\"\n target = name.lower()\n for key, value in headers.items():\n if key.lower() == target:\n return value\n return None\n\n\ndef _user_agent() -> str:\n \"\"\"The policy User-Agent: SDK identifier, plus an AI-agent slug when a known agent env var is set.\"\"\"\n ua = USER_AGENT${runtimeVersionLine}\n for env_var, slug in AI_AGENT_ENV_VARS.items():\n if os.environ.get(env_var):\n ua += \" agent/\" + slug\n break\n return ua\n\n\ndef _default_timeout() -> Optional[float]:\n${\n timeoutEnvVar\n ? ` \"\"\"The policy default timeout in seconds; TIMEOUT_ENV_VAR (milliseconds) overrides it when set.\"\"\"\n raw = os.environ.get(TIMEOUT_ENV_VAR)\n if raw:\n try:\n return float(raw) / 1000.0\n except ValueError:\n pass\n return DEFAULT_TIMEOUT`\n : ` \"\"\"The policy default timeout in seconds (None = no deadline).\"\"\"\n return DEFAULT_TIMEOUT`\n}\n\n\ndef _retry_delay(attempt: int, headers: Optional[dict[str, str]]) -> float:\n \"\"\"Seconds to sleep before retry attempt (0-based): a Retry-After header\n wins when honored; otherwise min(initial * multiplier**attempt, max) plus\n proportional random jitter.\"\"\"\n if HONOR_RETRY_AFTER_HEADER and headers:\n retry_after = _retry_after_seconds(headers)\n if retry_after is not None:\n return retry_after\n delay = min(BACKOFF_INITIAL_DELAY * (BACKOFF_MULTIPLIER ** attempt), BACKOFF_MAX_DELAY)\n return delay + delay * BACKOFF_JITTER * random.random()\n\n\ndef _retry_after_seconds(headers: dict[str, str]) -> Optional[float]:\n \"\"\"A Retry-After header as seconds: both the integer-seconds and the HTTP-date forms.\"\"\"\n value = _header(headers, \"Retry-After\")\n if value is None:\n return None\n value = value.strip()\n if value.isdigit():\n return float(value)\n try:\n parsed = email.utils.parsedate_to_datetime(value)\n except (TypeError, ValueError):\n return None\n if parsed is None:\n return None\n if parsed.tzinfo is None:\n parsed = parsed.replace(tzinfo=datetime.timezone.utc)\n return max(0.0, (parsed - datetime.datetime.now(datetime.timezone.utc)).total_seconds())\n\n\ndef _guard_options(params: Optional[dict[str, Any]]) -> None:\n \"\"\"Fail fast when a request-option key (api_key, max_retries, ...) is\n misplaced into request params — a misplaced credential would otherwise be\n sent on the wire and end up in provider logs.\"\"\"\n for key in params or ():\n if key in GUARDED_OPTION_KEYS:\n raise ValueError(\n \"request option \" + repr(key) + \" must be set on the client, not passed as a request parameter\"\n )\n\n\ndef encode(value: Any) -> Any:\n \"\"\"Wire-encode a request value: dataclasses -> dicts keyed by wire name\n (None fields dropped), enums -> their values; lists/dicts recurse.\"\"\"\n if isinstance(value, Enum):\n return encode(value.value)\n if dataclasses.is_dataclass(value) and not isinstance(value, type):\n out: dict[str, Any] = {}\n for f in dataclasses.fields(value):\n item = getattr(value, f.name)\n if item is None:\n continue\n out[f.metadata.get(\"wire\", f.name)] = encode(item)\n return out\n if isinstance(value, (list, tuple)):\n return [encode(item) for item in value]\n if isinstance(value, dict):\n return {key: encode(item) for key, item in value.items()}\n return value\n\n\ndef decode(tp: Any, value: Any) -> Any:\n \"\"\"Best-effort decode of parsed JSON into the generated models: dataclasses\n are built field-by-field (honoring wire names), enums by value; unknown\n shapes are returned as-is.\"\"\"\n if value is None or tp is None or tp is Any:\n return value\n origin = typing.get_origin(tp)\n if origin is not None:\n args = typing.get_args(tp)\n if origin is list and isinstance(value, list):\n item_tp = args[0] if args else Any\n return [decode(item_tp, item) for item in value]\n if origin is dict and isinstance(value, dict):\n value_tp = args[1] if len(args) > 1 else Any\n return {key: decode(value_tp, item) for key, item in value.items()}\n if origin is typing.Union:\n for arg in args:\n if arg is type(None):\n continue\n try:\n decoded = decode(arg, value)\n except Exception:\n continue\n if decoded is not value:\n return decoded\n return value\n return value\n if isinstance(tp, type) and issubclass(tp, Enum):\n try:\n return tp(value)\n except ValueError:\n return value\n if isinstance(tp, type) and dataclasses.is_dataclass(tp) and isinstance(value, dict):\n try:\n hints = typing.get_type_hints(tp)\n except Exception:\n hints = {}\n kwargs: dict[str, Any] = {}\n for f in dataclasses.fields(tp):\n wire = f.metadata.get(\"wire\", f.name)\n if wire in value:\n kwargs[f.name] = decode(hints.get(f.name, Any), value[wire])\n elif f.default is dataclasses.MISSING and f.default_factory is dataclasses.MISSING:\n kwargs[f.name] = None\n return tp(**kwargs)\n return value\n\n\ndef join_csv(value: Optional[list]) -> Optional[str]:\n \"\"\"Serialize an explode=false array parameter as one comma-joined value.\"\"\"\n if value is None:\n return None\n return \",\".join(_text(encode(item)) for item in value)\n\n\ndef _text(value: Any) -> str:\n if isinstance(value, bool):\n return \"true\" if value else \"false\"\n if isinstance(value, (dict, list)):\n return json.dumps(value)\n return str(value)\n\n\ndef _query_value(value: Any) -> Any:\n encoded = encode(value)\n if isinstance(encoded, list):\n return [_text(item) for item in encoded]\n return _text(encoded)\n\n\ndef _multipart(payload: dict[str, Any]) -> tuple[bytes, str]:\n \"\"\"Encode a multipart/form-data body (stdlib-only, manual boundary).\n bytes / file-like values become file parts; lists become repeated parts.\"\"\"\n boundary = uuid.uuid4().hex\n chunks: list[bytes] = []\n for name, value in payload.items():\n items = value if isinstance(value, list) else [value]\n for item in items:\n chunks.append((\"--\" + boundary + \"\\\\r\\\\n\").encode(\"utf-8\"))\n if isinstance(item, bytes) or hasattr(item, \"read\"):\n content = item if isinstance(item, bytes) else item.read()\n if isinstance(content, str):\n content = content.encode(\"utf-8\")\n filename = str(getattr(item, \"name\", name)).replace(\"\\\\\\\\\", \"/\").split(\"/\")[-1] or name\n disposition = 'Content-Disposition: form-data; name=\"' + name + '\"; filename=\"' + filename + '\"\\\\r\\\\n'\n chunks.append(disposition.encode(\"utf-8\"))\n chunks.append(b\"Content-Type: application/octet-stream\\\\r\\\\n\\\\r\\\\n\")\n chunks.append(content)\n else:\n chunks.append(('Content-Disposition: form-data; name=\"' + name + '\"\\\\r\\\\n\\\\r\\\\n').encode(\"utf-8\"))\n chunks.append(_text(item).encode(\"utf-8\"))\n chunks.append(b\"\\\\r\\\\n\")\n chunks.append((\"--\" + boundary + \"--\\\\r\\\\n\").encode(\"utf-8\"))\n return b\"\".join(chunks), \"multipart/form-data; boundary=\" + boundary\n\n\nclass Transport:\n def __init__(\n self,\n base_url: Optional[str] = None,\n api_key: Optional[str] = None,\n timeout: Optional[float] = None,\n ) -> None:\n self.base_url = (base_url or DEFAULT_BASE_URL).rstrip(\"/\")\n self.api_key = api_key\n self.timeout = timeout if timeout is not None else _default_timeout()\n self.user_agent = _user_agent()\n\n def request(\n self,\n method: str,\n path: str,\n query: Optional[dict[str, Any]] = None,\n body: Optional[dict[str, Any]] = None,\n headers: Optional[dict[str, Any]] = None,\n encoding: str = \"json\",\n raw: bool = False,\n idempotency: bool = False,\n ) -> Any:\n _guard_options(query)\n _guard_options(body)\n url = self.base_url + path\n params = {k: _query_value(v) for k, v in (query or {}).items() if v is not None}\n request_headers: dict[str, str] = {k: _text(v) for k, v in (headers or {}).items() if v is not None}\n request_headers.setdefault(\"User-Agent\", self.user_agent)\n data = None\n if body is not None:\n payload = {k: encode(v) for k, v in body.items() if v is not None}\n if encoding == \"multipart\":\n data, content_type = _multipart(payload)\n request_headers[\"Content-Type\"] = content_type\n elif encoding == \"form\":\n data = urllib.parse.urlencode(payload, doseq=True).encode(\"utf-8\")\n request_headers[\"Content-Type\"] = \"application/x-www-form-urlencoded\"\n else:\n data = json.dumps(payload).encode(\"utf-8\")\n request_headers[\"Content-Type\"] = \"application/json\"\n${authBlock} if idempotency:\n # One key per logical call, generated before the retry loop so every\n # retry of this request carries the SAME idempotency key.\n request_headers.setdefault(IDEMPOTENCY_HEADER, str(uuid.uuid4()))\n if params:\n url += \"?\" + urllib.parse.urlencode(params, doseq=True)\n attempt = 0\n while True:\n request = urllib.request.Request(url, data=data, method=method, headers=request_headers)\n try:\n with urllib.request.urlopen(request, timeout=self.timeout) as response:\n content = response.read()\n except urllib.error.HTTPError as error:\n error_headers = dict(error.headers.items())\n error_body = error.read()\n if attempt < MAX_RETRIES and error.code in RETRYABLE_STATUS_CODES:\n time.sleep(_retry_delay(attempt, error_headers))\n attempt += 1\n continue\n raise _error_for_status(error.code, error_headers, error_body) from None\n except OSError:\n # Connection/timeout errors (URLError, reset, DNS failure, socket timeout).\n if RETRY_CONNECTION_ERRORS and attempt < MAX_RETRIES:\n time.sleep(_retry_delay(attempt, None))\n attempt += 1\n continue\n raise\n if raw:\n return content\n return json.loads(content.decode(\"utf-8\")) if content else None\n`;\n}\n\n// ---- _pagination.py (only emitted when some method returns a page) -------\n\nexport function paginationPy(): string {\n return `from __future__ import annotations\n\nfrom dataclasses import dataclass, field\nfrom typing import Any, Generic, Iterator, TypeVar\n\nfrom ._transport import decode\n\nT = TypeVar(\"T\")\n\n\n@dataclass\nclass CursorPage(Generic[T]):\n \"\"\"One page of a cursor-paginated list: \\`data\\` plus a \\`has_more\\` marker.\"\"\"\n\n data: list[T] = field(default_factory=list)\n has_more: bool = False\n\n def __iter__(self) -> Iterator[T]:\n return iter(self.data)\n\n @classmethod\n def from_response(cls, item_type: Any, raw: Any) -> CursorPage[T]:\n payload = raw if isinstance(raw, dict) else {}\n data = [decode(item_type, item) for item in payload.get(\"data\") or []]\n return cls(data=data, has_more=bool(payload.get(\"has_more\") or False))\n\n\n@dataclass\nclass Page(Generic[T]):\n \"\"\"One page of a marker-less list: the whole collection in one \\`data\\` envelope.\"\"\"\n\n data: list[T] = field(default_factory=list)\n\n def __iter__(self) -> Iterator[T]:\n return iter(self.data)\n\n @classmethod\n def from_response(cls, item_type: Any, raw: Any) -> Page[T]:\n payload = raw if isinstance(raw, dict) else {}\n return cls(data=[decode(item_type, item) for item in payload.get(\"data\") or []])\n`;\n}\n","import type { Method, NamedType, Param, Resource, TypeRef } from '@xyd-js/opensdk-core';\nimport { type MethodExample, type PageName, planMethodExample, planOperation } from '@xyd-js/opensdk-framework';\n\nimport { renderPyExample } from './example-py';\nimport { pyPageName } from './method';\nimport { pascalCase, snakeCase } from './naming';\nimport { PyUses, pyType } from './pytype';\n\n// The SDK's OWN pytest suite — the artifact openai-python ships\n// (tests/api_resources/test_*.py). One tests/test_<resource>.py per top-level\n// resource constructs the generated Client (conftest fixture, mock base URL),\n// calls every method with shared-planner example values (a required-only case\n// plus a \"with all params\" case when the method has optionals), guards empty\n// path params, and structurally checks the response type via assert_matches_type.\n// SYNC ONLY — we have no async / raw / streaming client; those are follow-ups.\n\nconst DEFAULT_BASE_URL = 'http://127.0.0.1:4010';\n\n/** tests/utils.py — a pragmatic, stdlib-only structural type check. */\nexport function testUtilsPy(): string {\n return `from __future__ import annotations\n\nimport typing\nfrom typing import Any\n\n\ndef assert_matches_type(expected_type: Any, value: Any, *, path: Any = None) -> None:\n \"\"\"Pragmatic structural check for the generated test suite.\n\n Verifies the SHAPE of a response without being strict about deep generics:\n dataclass instances, the vendored pagination containers, primitives, lists\n and dicts are all accepted. A parameterized generic (e.g. CursorPage[Pet],\n list[str]) is matched against its ORIGIN only; Any / object / typing\n constructs (Optional, Union, ...) always match.\n \"\"\"\n origin = typing.get_origin(expected_type)\n if origin is not None:\n expected_type = origin\n if expected_type is Any or expected_type is object or expected_type is None:\n return\n if not isinstance(expected_type, type):\n return\n assert isinstance(value, expected_type), (\n f\"expected {getattr(expected_type, '__name__', expected_type)!r}, \"\n f\"got {type(value).__name__!r} (path={path})\"\n )\n`;\n}\n\n/** tests/conftest.py — the shared `client` fixture against the mock base URL. */\nexport function testConftestPy(pkg: string): string {\n return `from __future__ import annotations\n\nimport os\n\nimport pytest\n\nfrom ${pkg} import Client\n\nbase_url = os.environ.get(\"TEST_API_BASE_URL\", ${JSON.stringify(DEFAULT_BASE_URL)})\n\n\n@pytest.fixture\ndef client() -> Client:\n return Client(api_key=\"My API Key\", base_url=base_url)\n`;\n}\n\n/** One collected method: its client accessor chain + a test-name prefix. */\ninterface FlatMethod {\n method: Method;\n /** Attribute chain from `client`, e.g. [\"videos\", \"characters\"]. */\n chain: string[];\n /** Test-name qualifier for nested resources (empty for a top-level method). */\n namePrefix: string;\n}\n\n/** Walk the resource subtree, flattening every method with its client chain. */\nfunction collectMethods(resource: Resource, chain: string[], namePrefix: string, out: FlatMethod[]): void {\n for (const method of resource.methods || []) out.push({ method, chain, namePrefix });\n for (const sub of resource.resources || []) {\n const attr = snakeCase(sub.name);\n collectMethods(sub, [...chain, attr], `${namePrefix}${attr}_`, out);\n }\n}\n\n/** The first required string path param of a method (drives the guard test), or null. */\nfunction firstStringPathParam(method: Method): Param | null {\n for (const p of method.pathParams || []) {\n if (p.type?.kind === 'scalar' && p.type.scalar === 'string' && p.required !== false) return p;\n }\n return null;\n}\n\n/**\n * The type expression asserted against the call result: `bytes` for a binary\n * download, `<Page>[<Item>]` for a paginated list, the primary response type\n * otherwise, or null when the method has no response (no assertion emitted).\n */\nfunction responseTypeExpr(\n method: Method,\n types: Map<string, NamedType>,\n uses: PyUses,\n pages: Set<PageName>,\n): string | null {\n const plan = planOperation(method, types);\n if (plan.binaryContentType) return 'bytes';\n const page = pyPageName(plan);\n if (page) {\n pages.add(page);\n return `${page}[${pyType(method.pagination?.itemType as TypeRef | undefined, uses)}]`;\n }\n const primary = method.primaryResponse as TypeRef | undefined;\n if (!primary) return null;\n return pyType(primary, uses);\n}\n\n/** Positional path args followed by `name=value` keyword args for one example. */\nfunction renderCallArgs(ex: MethodExample): string {\n const parts = ex.pathArgs.map((pa) => renderPyExample(pa.value));\n for (const f of ex.fields) parts.push(`${snakeCase(f.name)}=${renderPyExample(f.value)}`);\n return parts.join(', ');\n}\n\n/** A `def test_...(self, client): result = call; assert_matches_type(...)` block. */\nfunction renderMethodTest(name: string, call: string, responseType: string | null): string {\n const lines = [` def ${name}(self, client: Client) -> None:`];\n if (responseType) {\n lines.push(` result = ${call}`);\n lines.push(` assert_matches_type(${responseType}, result, path=[\"response\"])`);\n } else {\n lines.push(` ${call}`);\n }\n return lines.join('\\n');\n}\n\n/** The empty-path-param guard test: an empty target raises ValueError. */\nfunction renderPathParamsTest(name: string, callChain: string, ex: MethodExample, target: Param): string {\n const n = snakeCase(target.name);\n const parts: string[] = [];\n for (const pa of ex.pathArgs) parts.push(pa.param === target ? '\"\"' : renderPyExample(pa.value));\n for (const f of ex.fields) parts.push(`${snakeCase(f.name)}=${renderPyExample(f.value)}`);\n return [\n ` def ${name}(self, client: Client) -> None:`,\n ` with pytest.raises(ValueError, match=r\"Expected a non-empty value for \\`${n}\\` but received ''\"):`,\n ` ${callChain}(${parts.join(', ')})`,\n ].join('\\n');\n}\n\n/** tests/test_<resource>.py for one top-level resource (walks its whole subtree). */\nexport function resourceTestPy(resource: Resource, pkg: string, types: Map<string, NamedType>): string {\n const uses = new PyUses();\n const pages = new Set<PageName>();\n let usesPytest = false;\n\n const collected: FlatMethod[] = [];\n collectMethods(resource, [snakeCase(resource.name)], '', collected);\n\n const blocks: string[] = [];\n for (const { method, chain, namePrefix } of collected) {\n const action = snakeCase(method.action);\n const base = `${namePrefix}${action}`;\n const callChain = `client.${[...chain, action].join('.')}`;\n const responseType = responseTypeExpr(method, types, uses, pages);\n\n const required = planMethodExample(method, types);\n blocks.push(renderMethodTest(`test_method_${base}`, `${callChain}(${renderCallArgs(required)})`, responseType));\n\n if (required.hasOptional) {\n const all = planMethodExample(method, types, { withOptional: true });\n blocks.push(\n renderMethodTest(`test_method_${base}_with_all_params`, `${callChain}(${renderCallArgs(all)})`, responseType),\n );\n }\n\n const target = firstStringPathParam(method);\n if (target) {\n usesPytest = true;\n blocks.push(renderPathParamsTest(`test_path_params_${base}`, callChain, required, target));\n }\n }\n\n const groups: string[][] = [['from __future__ import annotations']];\n const typingLine = uses.typingImport();\n if (typingLine) groups.push([typingLine]);\n if (usesPytest) groups.push(['import pytest']);\n const local = ['from tests.utils import assert_matches_type', `from ${pkg} import Client`, `from ${pkg}.models import * # noqa: F401,F403`];\n if (pages.size > 0) {\n const names = (['CursorPage', 'Page'] as const).filter((n) => pages.has(n));\n local.push(`from ${pkg}._pagination import ${names.join(', ')}`);\n }\n groups.push(local);\n\n const imports = groups.map((g) => g.join('\\n')).join('\\n\\n');\n const body = blocks.length ? blocks.join('\\n\\n') : ' pass';\n return `${imports}\\n\\n\\nclass Test${pascalCase(resource.name)}:\\n${body}\\n`;\n}\n","import type { ExampleValue } from '@xyd-js/opensdk-framework';\n\n// Renders the framework's language-neutral ExampleValue tree into a Python\n// literal, for the generated test suite (generateTests). The shared planner\n// (planExample / planMethodExample) decides WHAT a realistic example is; this\n// module only decides how Python spells it — so the Go and Python test suites\n// exercise byte-identical shapes and can never drift.\n\n/**\n * Render one ExampleValue as a Python literal expression. Object/map render as\n * dict literals keyed by the WIRE field name (our kwargs and request bodies\n * accept plain dicts, which the transport encodes); enums render as their raw\n * wire value (the transport encodes an Enum and its bare value identically, and\n * this keeps the test import-free of the enum symbol).\n */\nexport function renderPyExample(value: ExampleValue): string {\n switch (value.kind) {\n case 'string':\n return pyStr(value.value);\n case 'integer':\n return String(value.value);\n case 'number':\n return String(value.value);\n case 'boolean':\n return value.value ? 'True' : 'False';\n case 'null':\n return 'None';\n case 'binary':\n return 'b\"Example data\"';\n case 'enum':\n return pyLiteral(value.value);\n case 'const':\n return pyLiteral(value.value);\n case 'array':\n return `[${renderPyExample(value.item)}]`;\n case 'map':\n return `{\"key\": ${renderPyExample(value.value)}}`;\n case 'object':\n return value.fields.length === 0\n ? '{}'\n : `{${value.fields.map((f) => `${pyStr(f.name)}: ${renderPyExample(f.value)}`).join(', ')}}`;\n case 'union':\n return renderPyExample(value.variant);\n default:\n return 'None';\n }\n}\n\n/** A JSON scalar (enum/const wire value) as a Python literal. */\nfunction pyLiteral(v: unknown): string {\n if (v === null || v === undefined) return 'None';\n if (typeof v === 'boolean') return v ? 'True' : 'False';\n if (typeof v === 'number') return String(v);\n return pyStr(String(v));\n}\n\n/** A double-quoted Python string literal (JSON quoting is valid Python). */\nfunction pyStr(s: string): string {\n return JSON.stringify(s);\n}\n","import { type EmitterPublishOptions, runCommand } from '@xyd-js/opensdk-framework';\n\n/**\n * Publish the generated Python SDK to a PyPI-compatible index: `python -m build`\n * (needs the PyPA `build` package) then `twine upload`. Auth via TWINE_* env; the\n * token becomes TWINE_PASSWORD with the `__token__` username convention.\n */\nexport function publishPython(dir: string, opts: EmitterPublishOptions = {}): void {\n runCommand('python3', ['-m', 'build'], { cwd: dir });\n if (opts.dryRun) return;\n const args = ['upload'];\n if (opts.registry) args.push('--repository-url', opts.registry);\n args.push('dist/*');\n runCommand('twine', args, {\n cwd: dir,\n env: {\n ...process.env,\n TWINE_USERNAME: process.env.TWINE_USERNAME ?? '__token__',\n TWINE_PASSWORD: opts.token ?? process.env.TWINE_PASSWORD ?? 'opensdk',\n },\n });\n}\n","export { opensdkPython, pythonEmitter } from './emitter';\nexport { publishPython } from './publish';\nexport { writeProject } from '@xyd-js/opensdk-framework';\nexport type { OpensdkPythonOptions } from './types';\n"],"mappings":"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","names":["planOperation","sdkBehavior","planOperation","pyStr","planOperation","planOperation"]}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src';
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyd-js/opensdk-python",
|
|
3
|
+
"version": "0.0.0-build-f0c10f6-20260703195526",
|
|
4
|
+
"description": "OpenSDK IR -> a minimal Python SDK (stub target proving the IR is language-agnostic)",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@xyd-js/opensdk-core": "0.0.0-build-f0c10f6-20260703195526",
|
|
9
|
+
"@xyd-js/opensdk-framework": "0.0.0-build-f0c10f6-20260703195526"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@types/js-yaml": "^4.0.9",
|
|
13
|
+
"@types/node": "^20.9.0",
|
|
14
|
+
"js-yaml": "^4.1.0",
|
|
15
|
+
"rimraf": "^3.0.2",
|
|
16
|
+
"tsup": "^8.3.0",
|
|
17
|
+
"typescript": "^5.6.2",
|
|
18
|
+
"vitest": "^2.1.1",
|
|
19
|
+
"@xyd-js/openapi2opensdk": "0.0.0-build-f0c10f6-20260703195526",
|
|
20
|
+
"@xyd-js/opensdk-ci": "0.0.0-build-f0c10f6-20260703195526"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"clean": "rimraf dist",
|
|
24
|
+
"prebuild": "pnpm clean",
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"test": "vitest",
|
|
27
|
+
"ci:test": "vitest run",
|
|
28
|
+
"format": "bunx biome check --write src"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/emitter.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type NamedType, type OpensdkSpecJson, type Resource, walkMethods } from '@xyd-js/opensdk-core';
|
|
2
|
+
import type { Emitter, EmitterContext, GeneratedFile } from '@xyd-js/opensdk-framework';
|
|
3
|
+
import { generate, planOperation } from '@xyd-js/opensdk-framework';
|
|
4
|
+
|
|
5
|
+
import { pyPageName } from './method';
|
|
6
|
+
import { snakeCase } from './naming';
|
|
7
|
+
import { clientPy, modelsPy, pyproject, resolvePythonOptions, resourcesPy } from './project';
|
|
8
|
+
import { errorClassNames, paginationPy, transportPy } from './runtime';
|
|
9
|
+
import { resourceTestPy, testConftestPy, testUtilsPy } from './tests-py';
|
|
10
|
+
import type { OpensdkPythonOptions } from './types';
|
|
11
|
+
|
|
12
|
+
const resolve = (spec: OpensdkSpecJson, ctx: EmitterContext) =>
|
|
13
|
+
resolvePythonOptions(spec, ctx.emitterOptions as OpensdkPythonOptions);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The Python emitter plugin: a minimal, dependency-free SDK (dataclasses,
|
|
17
|
+
* enums, stdlib urllib transport). Pure capability methods over the IR.
|
|
18
|
+
*/
|
|
19
|
+
export const pythonEmitter: Emitter = {
|
|
20
|
+
language: 'python',
|
|
21
|
+
|
|
22
|
+
fileHeader(): string {
|
|
23
|
+
return 'Code generated by opensdk. DO NOT EDIT.';
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
generateProject(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {
|
|
27
|
+
const { pkg } = resolve(spec, ctx);
|
|
28
|
+
// User-owned scaffold: never clobber an existing pyproject.toml on regen.
|
|
29
|
+
return [{ path: 'pyproject.toml', content: pyproject(pkg, spec), writeMode: 'skipIfExists' }];
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
generateClient(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {
|
|
33
|
+
const { pkg, envVar } = resolve(spec, ctx);
|
|
34
|
+
// The public error surface: APIError plus the sdk.errors policy kinds.
|
|
35
|
+
const errors = ['APIError', ...errorClassNames(spec)];
|
|
36
|
+
const all = ['Client', ...errors].sort();
|
|
37
|
+
const init = `from ._client import Client\nfrom ._transport import ${errors.join(', ')}\n\n__all__ = [${all
|
|
38
|
+
.map((n) => JSON.stringify(n))
|
|
39
|
+
.join(', ')}]\n`;
|
|
40
|
+
return [
|
|
41
|
+
{ path: `${pkg}/__init__.py`, content: init },
|
|
42
|
+
{ path: `${pkg}/_client.py`, content: clientPy(spec, envVar) },
|
|
43
|
+
];
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
// models.py is emitted even for an empty symbol table: resources.py
|
|
47
|
+
// star-imports it, so the module must always exist.
|
|
48
|
+
generateTypes(_types: NamedType[], ctx: EmitterContext): GeneratedFile[] {
|
|
49
|
+
const { pkg } = resolve(ctx.spec, ctx);
|
|
50
|
+
return [{ path: `${pkg}/models.py`, content: modelsPy(ctx.spec) }];
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
generateResources(_resources: Resource[], ctx: EmitterContext): GeneratedFile[] {
|
|
54
|
+
const { pkg } = resolve(ctx.spec, ctx);
|
|
55
|
+
return [{ path: `${pkg}/resources.py`, content: resourcesPy(ctx.spec, ctx.types) }];
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
generateRuntime(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {
|
|
59
|
+
const { pkg, baseURL } = resolve(spec, ctx);
|
|
60
|
+
const files: GeneratedFile[] = [{ path: `${pkg}/_transport.py`, content: transportPy(spec, pkg, baseURL) }];
|
|
61
|
+
// Emitted only when some list method returns a page — a spec with no
|
|
62
|
+
// paginated endpoints gets no dead runtime code (mirrors the Go emitter).
|
|
63
|
+
if (walkMethods(spec).some(({ method }) => pyPageName(planOperation(method, ctx.types)) !== null)) {
|
|
64
|
+
files.push({ path: `${pkg}/_pagination.py`, content: paginationPy() });
|
|
65
|
+
}
|
|
66
|
+
return files;
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// The SDK's own pytest suite (openai-python's tests/api_resources/*). SYNC
|
|
70
|
+
// only — no async/raw/streaming client yet (follow-ups). Off via
|
|
71
|
+
// emitterOptions.tests === false; default ON. One test file per top-level
|
|
72
|
+
// resource plus the shared conftest fixture + assert_matches_type helper.
|
|
73
|
+
generateTests(spec: OpensdkSpecJson, ctx: EmitterContext): GeneratedFile[] {
|
|
74
|
+
if ((ctx.emitterOptions as OpensdkPythonOptions).tests === false) return [];
|
|
75
|
+
const { pkg } = resolve(spec, ctx);
|
|
76
|
+
const resources = spec.resources || [];
|
|
77
|
+
if (resources.length === 0) return [];
|
|
78
|
+
const files: GeneratedFile[] = [
|
|
79
|
+
{ path: 'tests/utils.py', content: testUtilsPy() },
|
|
80
|
+
{ path: 'tests/conftest.py', content: testConftestPy(pkg) },
|
|
81
|
+
];
|
|
82
|
+
for (const r of resources) {
|
|
83
|
+
files.push({ path: `tests/test_${snakeCase(r.name)}.py`, content: resourceTestPy(r, pkg, ctx.types) });
|
|
84
|
+
}
|
|
85
|
+
return files;
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Generate a minimal Python SDK from an OpenSDK IR. Back-compat wrapper:
|
|
91
|
+
* drives the `pythonEmitter` plugin through the framework orchestrator.
|
|
92
|
+
*/
|
|
93
|
+
export function opensdkPython(spec: OpensdkSpecJson, options: OpensdkPythonOptions = {}): Record<string, string> {
|
|
94
|
+
return generate(spec, pythonEmitter, options as Record<string, unknown>);
|
|
95
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ExampleValue } from '@xyd-js/opensdk-framework';
|
|
2
|
+
|
|
3
|
+
// Renders the framework's language-neutral ExampleValue tree into a Python
|
|
4
|
+
// literal, for the generated test suite (generateTests). The shared planner
|
|
5
|
+
// (planExample / planMethodExample) decides WHAT a realistic example is; this
|
|
6
|
+
// module only decides how Python spells it — so the Go and Python test suites
|
|
7
|
+
// exercise byte-identical shapes and can never drift.
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Render one ExampleValue as a Python literal expression. Object/map render as
|
|
11
|
+
* dict literals keyed by the WIRE field name (our kwargs and request bodies
|
|
12
|
+
* accept plain dicts, which the transport encodes); enums render as their raw
|
|
13
|
+
* wire value (the transport encodes an Enum and its bare value identically, and
|
|
14
|
+
* this keeps the test import-free of the enum symbol).
|
|
15
|
+
*/
|
|
16
|
+
export function renderPyExample(value: ExampleValue): string {
|
|
17
|
+
switch (value.kind) {
|
|
18
|
+
case 'string':
|
|
19
|
+
return pyStr(value.value);
|
|
20
|
+
case 'integer':
|
|
21
|
+
return String(value.value);
|
|
22
|
+
case 'number':
|
|
23
|
+
return String(value.value);
|
|
24
|
+
case 'boolean':
|
|
25
|
+
return value.value ? 'True' : 'False';
|
|
26
|
+
case 'null':
|
|
27
|
+
return 'None';
|
|
28
|
+
case 'binary':
|
|
29
|
+
return 'b"Example data"';
|
|
30
|
+
case 'enum':
|
|
31
|
+
return pyLiteral(value.value);
|
|
32
|
+
case 'const':
|
|
33
|
+
return pyLiteral(value.value);
|
|
34
|
+
case 'array':
|
|
35
|
+
return `[${renderPyExample(value.item)}]`;
|
|
36
|
+
case 'map':
|
|
37
|
+
return `{"key": ${renderPyExample(value.value)}}`;
|
|
38
|
+
case 'object':
|
|
39
|
+
return value.fields.length === 0
|
|
40
|
+
? '{}'
|
|
41
|
+
: `{${value.fields.map((f) => `${pyStr(f.name)}: ${renderPyExample(f.value)}`).join(', ')}}`;
|
|
42
|
+
case 'union':
|
|
43
|
+
return renderPyExample(value.variant);
|
|
44
|
+
default:
|
|
45
|
+
return 'None';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A JSON scalar (enum/const wire value) as a Python literal. */
|
|
50
|
+
function pyLiteral(v: unknown): string {
|
|
51
|
+
if (v === null || v === undefined) return 'None';
|
|
52
|
+
if (typeof v === 'boolean') return v ? 'True' : 'False';
|
|
53
|
+
if (typeof v === 'number') return String(v);
|
|
54
|
+
return pyStr(String(v));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A double-quoted Python string literal (JSON quoting is valid Python). */
|
|
58
|
+
function pyStr(s: string): string {
|
|
59
|
+
return JSON.stringify(s);
|
|
60
|
+
}
|
package/src/index.ts
ADDED
package/src/method.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OperationPlan } from '@xyd-js/opensdk-framework';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The Python page container for a planned method. All "what should this
|
|
5
|
+
* method do" derivations (binary content type, encoding, pagination gates,
|
|
6
|
+
* idempotency) come from the framework's shared `planOperation()` — this
|
|
7
|
+
* adapter only narrows the plan to what the Python runtime can render:
|
|
8
|
+
* OffsetPage has no vendored Python container yet, so offset-style methods
|
|
9
|
+
* keep the raw envelope return.
|
|
10
|
+
*/
|
|
11
|
+
export function pyPageName(plan: OperationPlan): 'CursorPage' | 'Page' | null {
|
|
12
|
+
return plan.pageName === 'CursorPage' || plan.pageName === 'Page' ? plan.pageName : null;
|
|
13
|
+
}
|
package/src/naming.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Split an identifier (camel/snake/kebab/space/dot) into lowercase words. */
|
|
2
|
+
export function splitWords(input: string): string[] {
|
|
3
|
+
return input
|
|
4
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
5
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
6
|
+
.split(/[^a-zA-Z0-9]+/) // split on ANY non-alphanumeric so wire junk (e.g. `ids[]`) can't leak into an identifier
|
|
7
|
+
.map((w) => w.trim().toLowerCase())
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Prefix `_` when an identifier would start with a digit (illegal in Python). */
|
|
12
|
+
function safeIdent(s: string): string {
|
|
13
|
+
return /^[0-9]/.test(s) ? `_${s}` : s;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** PascalCase, e.g. "pet-list" → "PetList". */
|
|
17
|
+
export function pascalCase(input: string): string {
|
|
18
|
+
const s = splitWords(input)
|
|
19
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
20
|
+
.join('');
|
|
21
|
+
return safeIdent(s);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** snake_case (Python identifiers), e.g. "petId" → "pet_id". */
|
|
25
|
+
export function snakeCase(input: string): string {
|
|
26
|
+
const s = safeIdent(splitWords(input).join('_'));
|
|
27
|
+
return PY_KEYWORDS.has(s) ? `${s}_` : s;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A Python module/package name: snake_case, alphanumerics + underscore only. */
|
|
31
|
+
export function pyModuleName(input: string): string {
|
|
32
|
+
const s = splitWords(input).join('_').replace(/[^a-z0-9_]/g, '');
|
|
33
|
+
return s || 'client';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** SCREAMING_SNAKE_CASE, e.g. "petstore" → "PETSTORE" (enum members: `_` prefix if digit-leading). */
|
|
37
|
+
export function screamingSnakeCase(input: string): string {
|
|
38
|
+
return safeIdent(splitWords(input).join('_').toUpperCase().replace(/[^A-Z0-9_]/g, ''));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const PY_KEYWORDS = new Set([
|
|
42
|
+
'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif',
|
|
43
|
+
'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda',
|
|
44
|
+
'none', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield',
|
|
45
|
+
]);
|