Replace vendored DI with uncalled-for#3301
Conversation
|
@jlowin this draft is still pointing to a branch of docket where I'm validating that we won't have any compatibility problems with 2.x when I release it. Will bump the version here once I'm sure. |
Test Failure Analysis
Summary: Two integration tests in Root Cause: The failures are transient network timeouts against an external third-party service. Both Suggested Solution: Re-run the failed integration test job. These failures are caused by external service unavailability, not by code changes in this PR. No code modifications are needed. Detailed AnalysisFailing tests (both in
Error pattern (identical for both): The test logs show the client dispatched the call but the remote server never responded: The thread dump at timeout time shows the asyncio event loop stuck in I/O polling: selectors.EpollSelector.select(timeout=29.745)
fd_event_list = self._selector.poll(timeout, max_ev)
E Failed: Timeout (>30.0s) from pytest-timeout.These tests require Related Files
|
3129137 to
41dc895
Compare
Test Failure Analysis
Summary: The integration test Root Cause: The timeout occurred inside Suggested Solution: Re-run the failed integration test job — this looks like a flaky failure due to CI environment performance variability and/or the live-fetched GitHub schema having grown. If it consistently fails after re-runs, the schema should be pinned to a specific commit/tag rather than fetching from Detailed AnalysisFailing test: Error: Stack trace at timeout: Why this is likely not caused by the PR:
Related Files
|
|
I believe this also closes #3251 |
|
I think it could! We can do a little more here to support |
|
I took off the |
FastMCP vendored a minimal DI engine extracted from Docket (~164 lines) with try/except fallback patterns everywhere. The `uncalled-for` package is a clean, typed extraction of this same system, and since Docket will also depend on it (chrisguidry/docket#353), `uncalled_for.Dependency` becomes the single canonical base class. This deletes the `_vendor/docket_di/` directory, replaces all the try/except import patterns with direct `uncalled_for` imports, and updates the `Dependency.execution` → `current_execution` ContextVar references to match the Docket branch. The `Progress` class now delegates to an internal impl and returns `self` from `__aenter__` (matching Docket's pattern) so that ty's generic resolution works without `type: ignore` suppressions. Temporarily points pydocket at the `use-uncalled-for` branch so both sides can be validated together in CI. 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.6 <[email protected]>
Internal code like azure.py should import from the fastmcp namespace rather than reaching into uncalled_for directly. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The DI engine now comes from uncalled-for, so the docs should credit it alongside Docket. Also updates the Docket docs link to docket.lol. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Enters a SharedContext at server lifetime so that Shared() dependencies from uncalled-for resolve once and are cached across tool/resource/prompt calls. When running with docket, the Worker already handles this; this covers the non-docket path and direct call_tool() usage. Also re-exports Shared from fastmcp.dependencies. Closes #3251 Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
93cff7a to
9c53f7e
Compare
Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 108bd684c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The old `_ensure_shared_context` on the server called `__aenter__()` on a lazy `SharedContext` but never `__aexit__()`, leaking the exit stack and its resources. Moved the SharedContext management into Context's own enter/exit so it's properly paired: when docket is available the lifespan handles it, otherwise Context creates and cleans up a per-request one. Updated Shared() tests to use Client (which runs the lifespan) rather than calling server methods directly, since cross-request sharing requires a lifespan. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

FastMCP vendored a minimal DI engine extracted from Docket (~164 lines) with try/except fallback patterns everywhere. The
uncalled-forpackage is a clean, typed extraction of this same system, and since Docket will also depend on it (chrisguidry/docket#353),uncalled_for.Dependencybecomes the single canonical base class.This deletes the
_vendor/docket_di/directory, replaces all the try/except import patterns with directuncalled_forimports, and updates theDependency.execution→current_executionContextVar references to match the Docket branch. TheProgressclass now delegates to an internal impl and returnsselffrom__aenter__(matching Docket's pattern) so that ty's generic resolution works withouttype: ignoresuppressions.Temporarily points pydocket at the
use-uncalled-forbranch so both sides can be validated together in CI. Once chrisguidry/docket#353 is merged and released, the pydocket dep goes back to a normal version pin.Closes #3251
Makes #3292 better
(Maybe) closes #3320
🤖 Generated with Claude Code