Repository navigation
Ship type information and enforce strict typing - #15
Draft
hansoutset wants to merge 5 commits into
Draft
hansoutset wants to merge 5 commits into
hansoutset wants to merge 5 commits into
Conversation
- Add py.typed marker (packaged via package_data) and Typing :: Typed classifier - Annotate remaining untyped functions; parametrize bare dict/Message/CallbackStorage generics - Fix DedupWorkflowCallbackStorage typing: pass WorkflowRefT through to the base class and stop reusing one variable for two types in retrieve() - Configure mypy (strict for the package, default checks for tests) and run it in CI across the Python x dramatiq matrix Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf4k4mZyJvX9wYNJt9MCRZ
Drop the relaxed-flags override for tests so the whole package is held to strict. Test message ids are now strings, matching dramatiq's Message type. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf4k4mZyJvX9wYNJt9MCRZ
- Add `-> None` to Chain/Group/WithDelay.__init__ (flagged by pyrefly) - Workflow now stamps int(time.time() * 1000), matching dramatiq's Message type and its own default, instead of a float - Tighten test annotations for pyrefly; add a ty ignore next to the mypy one - CI: pyright joins mypy as a blocking check; pyrefly and ty run pinned but non-blocking while they're pre-1.0 / fast-moving Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf4k4mZyJvX9wYNJt9MCRZ
- unserialize_workflow(_or_none) take `object`: the input is decoded broker data validated at runtime, so callers must go through the existing checks - Drop AtMostOnceBarrier's dead *args: dramatiq's Barrier.__init__/wait accept no extra positionals, so any value passed already raised TypeError - Document why WorkflowType keeps Message[Any] (invariant before dramatiq 1.18) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf4k4mZyJvX9wYNJt9MCRZ
The other tests build messages from MagicMock actors, so type checkers never saw real Message[R] types flowing into Chain/Group/WithDelay. This caught a Message[object] regression that only fails on dramatiq < 1.18. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf4k4mZyJvX9wYNJt9MCRZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes
dramatiq-workflowa typed library: it now shipspy.typed, the package and tests passmypy --strict, and CI checks it with mypy, pyright, pyrefly and ty across the Python × dramatiq matrix.Changes
Packaging
py.typedmarker, included viapackage_data, and theTyping :: Typedclassifier. Without the marker, type checkers ignored this package's annotations for anyone who installed it.Library typing
dict[str, Any],Message[Any],CallbackStorage[Any]). Public aliases stay compatible for existing users.DedupWorkflowCallbackStoragegenerics:WorkflowRefTis now passed through to theCallbackStoragebase, andretrieve()no longer reuses one variable for two types.unserialize_workflow/unserialize_workflow_or_nonetakeobjectinstead ofAny. The input is decoded broker data that is validated at runtime.WorkflowTypekeepsMessage[Any]rather thanMessage[object], becauseMessage's type parameter is invariant before dramatiq 1.18. There is a comment in the code explaining this.Small runtime changes
Workflownow stampsmessage_timestamp=int(time.time() * 1000)instead of a float, matching dramatiq'sMessagetype and its own default.AtMostOnceBarrier's dead*argsfrom__init__andwait. dramatiq'sBarrieraccepts no extra positional arguments, so passing any already raisedTypeError.Tests
mypy --strict. Test message ids are now strings, matching dramatiq'sMessagetype.tests/test_typing.pybuilds workflows from real@dramatiq.actormessages. The other tests useMagicMockactors, so type checkers never saw realMessage[R]types. I confirmed this test fails under dramatiq 1.17.1 ifWorkflowTypeis changed toMessage[object].Tooling / CI
make typecheck(mypy + pyright) is a blocking CI step.make pyreflyandmake tyrun as pinned, non-blocking steps (continue-on-error) while those checkers are pre-1.0 or changing quickly.requirements.txt.Verification (local)
With CI-equivalent installs on Python 3.10 and 3.14 × dramatiq 1.17.1 and 2.2.1:
--strict, pyright, pyrefly and ty report 0 errors.py.typed. A consumer script type-checks clean under mypy--strictagainst the installed package and reports errors for invalid workflow arguments.The full CI matrix has not run yet; this PR is its first run.
Notes
requirements.txtpinsdramatiq==1.17.1, and the laterpip install "dramatiq~=1.0"is already satisfied by that pin.🤖 Generated with Claude Code
https://claude.ai/code/session_01Hf4k4mZyJvX9wYNJt9MCRZ