Skip to content

Let Python SDKs wire hand-written response hooks - #60

Merged
glenn-jocher merged 1 commit into
mainfrom
feat/python-hooks-provider
Oct 30, 2026
Merged

glenn-jocher merged 1 commit into
mainfrom
feat/python-hooks-provider

Conversation

@glenn-jocher

@glenn-jocher glenn-jocher commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds an optional python.hooksProvider config key, the response-hook counterpart of authProvider. It names a consumer-owned Python file that the generator copies to <package>/_hooks.py. The file must export response_hook(response) and async def async_response_hook(response). The generated sync and async clients then register them as httpx response event hooks on the clients they build.

  • A caller-supplied http_client is used as is (no mutation or merging), matching how timeout already applies only to SDK-built clients. The README and, when the option is set, the generated http_client docstring say so.
  • Nothing API-specific lives in the generator.
  • First consumer: ultralytics/sdk, where the Platform SDK will wake a local On Premise worker after creating its job (Wake the local On Premise worker after the CLI creates its job sdk#131).

Non-test code nets +1 line (the readme, authProvider and hooksProvider path resolution share one loop); +25 with the test.

Validation

  • Without the option, output is byte-identical before and after (raw generatePython and the full bun run generate) for the example config and the real ultralytics/sdk config. The latter uses authProvider and a CLI, so both branches are covered. Generation is deterministic.
  • New end-to-end test: a Bun.serve server on port 0 and a hooks file that prints from each hook. It calls the generated SDK sync, sync with a custom http_client, and async, and asserts exactly ["sync 200", "async 200"]. Disabling the sync wiring fails it.
  • bun run generate, typecheck, lint, knip, test (21 pass) and build. With the option set, the generated package passes ruff check, compileall and import.

🛠️ PR Summary

Made with ❤️ by Ultralytics Actions

🌟 Summary

Adds optional Python response-hook support by copying a consumer-provided hooks module into generated SDKs and registering its hooks on SDK-created HTTP clients.

📊 Key Changes

  • Adds python.hooksProvider, with relative paths resolved against the config file, and copies the module into the generated package as _hooks.py.
  • Generated sync and async clients import and register response_hook and async_response_hook as httpx response event hooks when the option is configured.
  • Documents that a caller-supplied http_client is used unchanged and does not receive the configured hooks.

🎯 Purpose & Impact

  • SDK consumers can run custom logic after responses from clients built by the SDK; callers using a custom HTTP client must register hooks on that client themselves.

@UltralyticsAssistant UltralyticsAssistant added documentation Improvements or additions to documentation enhancement New feature or request labels Oct 30, 2026
@UltralyticsAssistant

Copy link
Copy Markdown
Member

👋 Hello @glenn-jocher, thank you for submitting a ultralytics/openapi 🚀 PR! This automated message confirms your contribution was received, and an Ultralytics engineer will assist with the review. To ensure a seamless integration of your work, please review the following checklist:

  • ✅ Define a Purpose: Clearly explain the purpose of your fix or feature in your PR description, and link to any relevant issues. Ensure your commit messages are clear, concise, and adhere to the project's conventions.
  • ✅ Synchronize with Source: Confirm your PR is synchronized with the ultralytics/openapi main branch. If it's behind, update it by clicking the 'Update branch' button or by running git pull and git merge main locally.
  • ✅ Ensure CI Checks Pass: Verify all Ultralytics Continuous Integration (CI) checks are passing. If any checks fail, please address the issues.
  • ✅ Update Documentation: Update the relevant documentation for any new or modified features.
  • ✅ Add Tests: If applicable, include or update tests to cover your changes, and confirm that all tests are passing.
  • ✅ Sign the CLA: Please ensure you have signed our Contributor License Agreement if this is your first Ultralytics PR; the CLA check will comment with signing instructions if needed.
  • ✅ Minimize Changes: Limit your changes to the minimum necessary for your bug fix or feature addition. "It is not daily increase but daily decrease, hack away the unessential. The closer to the source, the less wastage there is." — Bruce Lee

For more guidance, please refer to our Contributing Guide. Don't hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀

@UltralyticsAssistant UltralyticsAssistant left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 PR Review

Made with ❤️ by Ultralytics Actions

Reviewed the configuration path resolution, generated sync/async client wiring, custom-client behavior, provider copying, documentation, and end-to-end test. The opt-in hooks remain consumer-owned and default generation is unchanged. LGTM.

@glenn-jocher
glenn-jocher merged commit 3aba4be into main Oct 30, 2026
7 checks passed
@glenn-jocher
glenn-jocher deleted the feat/python-hooks-provider branch October 30, 2026 10:53
@UltralyticsAssistant

Copy link
Copy Markdown
Member

🎉 This PR has been merged—thank you, @glenn-jocher! Configurable response hooks let SDK users run custom logic after responses from generated sync and async clients, while caller-provided HTTP clients remain unchanged.

“Alone we can do so little; together we can do so much.” — Helen Keller

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants