Skip to content

Commit 9bbca00

Browse files
committed
feat: ship a useful default Python init template
The empty class generated by `dagger module init python` makes every user recreate the same Workspace-to-Directory-to-Container plumbing before the module can do useful work. TypeScript SDK #10 established a small working module as the cross-SDK default while retaining a blank starter explicitly. Add the Python equivalent: capture the filtered workspace source, accept a pinned base image through the constructor, and return a container with that source mounted. Keep the target project generic; uv remains an implementation choice in the module's generated pyproject rather than an assumption about the workspace being automated. Use Python's alternate `create` constructor to translate the user-facing Workspace input into the object's durable `source` and `base_image_address` fields. Module objects are reconstructed from those fields before later function calls, so the dataclass-generated `__init__` must remain available for state hydration. Rename the previous minimal template to `empty`, leave `legacy` unchanged, and make `default` explicit in the init signature. The constructor argument is named `ws` so it does not collide with the CLI's top-level `--workspace` flag. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
1 parent 5ee93fe commit 9bbca00

5 files changed

Lines changed: 57 additions & 4 deletions

File tree

python-sdk.dang

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,15 @@ type PythonSdk {
136136
new module's `path`. Engine-owned files (dagger-module.toml, workspace config
137137
updates) are produced by the engine and merged with this changeset.
138138

139-
Pass `template` to materialize files from templates/<template>. The empty
140-
default uses this module's minimal template.
139+
Pass `template` to pick a starter under templates/<template>. It defaults to
140+
`default` (a small working module). Use `empty` for a bare object class. An
141+
explicitly empty template also selects `default` for compatibility.
141142

142143
Pass `pythonVersion`, `useUv`, or `baseImage` to customize the generated
143144
pyproject.toml. Defaults leave the template untouched: the template's Python
144145
version is used, uv is enabled, and no base image override is written.
145146
"""
146-
pub initModule(ws: Workspace!, name: String!, path: String!, template: String! = "", pythonVersion: String! = "", useUv: Boolean! = true, baseImage: String! = ""): Changeset! {
147+
pub initModule(ws: Workspace!, name: String!, path: String!, template: String! = "default", pythonVersion: String! = "", useUv: Boolean! = true, baseImage: String! = ""): Changeset! {
147148
let rawPath = path.trimPrefix("./").trimPrefix("/")
148149

149150
let modPath = if (rawPath == "" or rawPath == ".") {
@@ -154,7 +155,7 @@ type PythonSdk {
154155
rawPath.trimSuffix("/")
155156
}
156157

157-
let selectedTemplate = if (template == "") { "minimal" } else { template }
158+
let selectedTemplate = if (template == "") { "default" } else { template }
158159

159160
if (currentModule.source.exists("templates/" + selectedTemplate) == false) {
160161
raise "unknown init template: " + template
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import dagger
2+
from dagger import dag, function, object_type
3+
4+
5+
@object_type
6+
class {{ .ModuleType }}:
7+
source: dagger.Directory
8+
base_image_address: str
9+
10+
@classmethod
11+
def create(
12+
cls,
13+
ws: dagger.Workspace,
14+
base_image_address: str = "alpine:3.21",
15+
):
16+
return cls(
17+
source=ws.directory(
18+
"/",
19+
exclude=[
20+
"**/.dagger",
21+
"**/.git",
22+
"**/.venv",
23+
"**/__pycache__",
24+
"**/node_modules",
25+
"**/dist",
26+
],
27+
),
28+
base_image_address=base_image_address,
29+
)
30+
31+
@function
32+
def container(self) -> dagger.Container:
33+
"""A container with the workspace source, ready to build."""
34+
return (
35+
dag.container()
36+
.from_(self.base_image_address)
37+
.with_directory("/src", self.source)
38+
.with_workdir("/src")
39+
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[project]
2+
name = "{{ .ModuleName }}"
3+
version = "0.1.0"
4+
requires-python = ">=3.14"
5+
dependencies = ["dagger-io"]
6+
7+
[build-system]
8+
requires = ["uv_build>=0.8.4,<0.9.0"]
9+
build-backend = "uv_build"
10+
11+
[tool.uv.sources]
12+
dagger-io = { path = "sdk", editable = true }

templates/minimal/src/{{.ModulePackage}}/__init__.py.tmpl renamed to templates/empty/src/{{.ModulePackage}}/__init__.py.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dagger import object_type
22

3+
34
@object_type
45
class {{ .ModuleType }}:
56
pass

0 commit comments

Comments
 (0)