Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .dagger/lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[["version","1"]]
["","container.from",["docker.io/library/golang:1.25-alpine","linux/arm64"],"sha256:8d22e29d960bc50cd025d93d5b7c7d220b1ee9aa7a239b3c8f55a57e987e8d45","pin"]
["","container.from",["docker.io/library/golang:1.26-alpine","linux/arm64"],"sha256:70b46548e42db77e0966aaf3619fd068734dc6c77584d526b91126504fd95816","pin"]
["","git.head",["https://github.com/dagger/sdk-sdk"],"d1532df4f7d322a7bdab02487accde9d21bbb464","float"]
69 changes: 69 additions & 0 deletions .dagger/modules/e2e/main.dang
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ type E2e {
assert(contains(changes.addedPaths, path), "expected added path: " + path)
}

"""
Assert the exact set of files a changeset added, so an extra or a missing
file fails instead of slipping past a contains-only assertion. Directory
entries are ignored: they only ever appear because of a file below them.
"""
let assertPaths(changes: Changeset!, want: [String!]!): Void {
let got = changes.addedPaths.filter { path => path.hasSuffix("/") == false }
assert(
got.length == want.length and want.all { path => contains(got, path) },
"expected exactly [" + want.join(", ") + "], got [" + got.join(", ") + "]",
)
}

"""
Assert that a string contains a substring.
"""
Expand Down Expand Up @@ -163,8 +176,63 @@ type E2e {
assert(defaultChanges.removedPaths.length == 0, "init unexpectedly removed files")
assertContains(defaultChanges.layer.file(defaultPath + "/src/init_default/__init__.py").contents, "class InitDefault:", "default template did not render the module type")

let defaultPyproject = defaultChanges.layer.file(defaultPath + "/pyproject.toml").contents
assertContains(defaultPyproject, "name = \"init-default\"", "default template did not render the module name into pyproject.toml")
assertNotContains(defaultPyproject, "{{", "default template left an unexpanded action in pyproject.toml")

assertContains(legacyChanges.layer.file(legacyPath + "/src/init_legacy/main.py").contents, "class InitLegacy:", "legacy template did not render the module type")

assertPaths(defaultChanges, [
defaultPath + "/pyproject.toml",
defaultPath + "/src/init_default/__init__.py",
])
assertPaths(legacyChanges, [
legacyPath + "/.gitattributes",
legacyPath + "/.gitignore",
legacyPath + "/pyproject.toml",
legacyPath + "/src/init_legacy/__init__.py",
legacyPath + "/src/init_legacy/main.py",
])
assertContains(legacyChanges.layer.file(legacyPath + "/.gitignore").contents, "/sdk", "legacy template dropped the contents of a non-template file")

null
}

"""
A module name should render the same type and package names the templates
expect, for every spelling a user might pass to init.

The package name must match what the `uv_build` backend derives from the
project name in pyproject.toml, or the module cannot be loaded: that is why
`s3-bucket` has to yield `s3_bucket`.

The `HTTPServer` row characterizes the current conversion rather than a
desired outcome — `Httpserver` is what it renders today, and changing it
deliberately is fine.
"""
pub initNamingCheck(ws: Workspace!): Void @check {
[
["my-module", "MyModule", "my_module"],
["my_module", "MyModule", "my_module"],
["myModule", "MyModule", "my_module"],
["simple", "Simple", "simple"],
["s3-bucket", "S3Bucket", "s3_bucket"],
["HTTPServer", "Httpserver", "http_server"],
].each { naming =>
let name = naming.takeFirst(1).join("")
let type = naming.dropFirst(1).takeFirst(1).join("")
let package = naming.takeLast(1).join("")
let path = outputRoot + "/init-naming/" + name

let changes = pythonSdk.initModule(ws, name: name, path: path)
assertAdded(changes, path + "/src/" + package + "/__init__.py")
assertContains(
changes.layer.file(path + "/src/" + package + "/__init__.py").contents,
"class " + type + ":",
"init " + name + " did not render the type as " + type,
)
}

null
}

Expand All @@ -183,6 +251,7 @@ type E2e {
"template_default",
)
assertContainsAll(defaultSource, [
"from __future__ import annotations",
"class TemplateDefault:",
"@classmethod\n def create(",
"ws: dagger.Workspace",
Expand Down
Loading