feat: ship a useful default Python init template - #10
Conversation
e4168db to
fc92962
Compare
fc92962 to
3f513fe
Compare
`dagger module init python` currently generates an empty object. It is a valid module, but it does not give users a useful starting point or show how a workspace becomes a container. Generate a small working module by default. It keeps the workspace source, lets users choose the base image, and exposes a container function with the source mounted at `/src`. Python needs the public `create` method because Dagger later rebuilds the object from its fields. Keeping the generated `__init__` available makes that reconstruction work when another function is called. The previous blank template remains available as `empty`, while `legacy` stays unchanged. Name the workspace argument `ws` to avoid clashing with the CLI's top-level `--workspace` flag. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
The init command now has two useful starting points: the working default and the blank `empty` template. Cover both through `initModule`, including the existing behavior where an explicitly empty template name selects the default. Check the generated source rather than the template helpers so the test sees what users actually receive. Also call the generated container function. This catches a Python-specific failure where the module loads correctly but fails when Dagger rebuilds the object before the next function call. Keep the expected and unwanted snippets together so reviewers can read the generated source contract without working through repeated assertions. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
Bring newly generated projects in line with the versions we support today: Python 3.14, uv_build through the 0.11 line, and Alpine 3.24 for the new default container. Keep uv_build's lower bound at 0.8.4 because the engine already includes a compatible version. This avoids an unnecessary download while still allowing current releases below 0.12. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
3f513fe to
6b06cbc
Compare
TomChv
left a comment
There was a problem hiding this comment.
LGTM, just left a small comment about create but it's mergeable as it is :)
| base_image_address: str | ||
|
|
||
| @classmethod | ||
| def create( |
There was a problem hiding this comment.
Are users familiar with this notation? I saw your comment on the PR description about it but if that's confusing for users maybe it's better to use __init__? Or maybe explain it in the README.md
Can't you have the workspace in the constructor with __init__?
eunomie
left a comment
There was a problem hiding this comment.
I think that looks good to me.
kMy only concern with the template is if you just discover dagger it might be a bit rough to only get a container, not sure you know what to do with it. Maybe 1 single function that exposes something should be nice. I don't have super nice ideas, but that could be for instance just to output the entries of the source directory. It's not that useful but 🤷
But it also depends on the goal of the template. My remark is about a user not knowing a lot about dagger. But if I know about dagger, and just want to bootstrap a new module, then that feels good as it's very often you want to have a container with the source dir mounted. So feel free to ignore my first remark :-)
As a follow up (so not preventing at all to merge it, just FYI) I'll look into simplifying the directory structure when we create a new python module. It will have a small impact on the output of an init, but not on the content of the template.
Why
Today,
dagger module init python hellocreates a valid module whose object only containspass. It works, but it does not show a new user how to turn their workspace into something useful.For the 1.0 experience tracked in dagger/dagger#13626, the default should be a small working example. This follows the direction established by dagger/typescript-sdk#10.
What changes
The new default stores a filtered view of the caller's workspace and exposes a
containerfunction with that source mounted at/src. It uses Alpine 3.24 by default, while keeping the image configurable.The template stays deliberately generic: it does not assume the workspace is a Python project, uses uv, or has a particular build command. uv is only used to package the generated Dagger module.
The previous blank template is now available as
--template empty.legacyis unchanged, and an explicitly empty template value continues to select the default for compatibility.The generated project files also move to Python 3.14 and accept
uv_buildreleases below 0.12. The lower bound remains compatible with the uv version already bundled in the engine.Why
createinstead of__init__The template uses the Python SDK's supported alternate
createconstructor. It receives the caller's workspace and converts it into the fields Dagger stores between function calls. This keeps the user-facing workspace input separate from the state Dagger needs to restore later.Try it
From an empty Git repository:
dagger api functions helloshould listcontainer, and the final command should print/src.To check the blank template:
The generated
Blankclass should contain onlypass.Verification
All 12 checks pass against
v1.0.0-beta.7and the locally rebuilt engine fromdagger/dagger@7a6730c178228b4a3a8273664d319578892b7fe1. A fresh generated module also returned Alpine3.24.1when invoked with the beta.7 CLI.