#The reliance on code gen somewhat
1 messages · Page 1 of 1 (latest)
I hear you, but I want to be clear that codegen is only necessary to provide a better DX. It's not strictly necessary for using Dagger in any shape or form, including Zenith. More specifically, we're looking for the kind of experience where, via LSP, you get autocompletion and hints on function arguments and descriptions, and with a code structure that feels natural to programmers of the language. How else can you provide this without codegen?
Take an example using Python. Most basic support is to run string based queries to the API:
result = client.execute(
gql("""
query {
container {
from(address: "python") {
withExec(args: ["python", "-V"]) {
stdout
}
}
}
}
"""
)
)
print(result['container']['from']['withExec']['stdout'])
That's error prone though and harder to programmatically combine or build the query.
That's why we usually use a query builder. In Python it looks like this:
ds = DSLSchema(session.client.schema)
query = dsl_gql(
DSLQuery(
ds.Query.container.select(
getattr(ds.Container, "from")(address="python").select(
ds.Container.with_exec(args=["python", "-V"]).select(
ds.Container.stdout
)
)
)
))
result = session.execute(query)
print(result['container']['from']['withExec']['stdout'])
That may seem like it's typed, but it's not. This is using a magic __getattribute__ accessor so ds.Query.container is similar to ds["Query"]["container"] and won't help you with any autocompletion or IDE feedback. It'll fail on schema validation though, even before sending the request, but only after you run it.
With codegen we can fix all of that, so it becomes simply this:
result = await (
client.container()
.from_("python")
.with_exec(["python", "-V"])
.stdout()
)
print(result)
@faint forum , with Zenith, you're adding fields and types to the API. If you don't codegen, you still can have the core types that are already codegened in the precompiled jar, but not for any extensions from dependent modules. For those, you'll have to resort to a lower level query builder or query strings like above.
That's why we're baking codegen into Zenith, but we want it to be as seamless as possible. It can be done automatically for you and it could be hidden away but one constraint is to also have the new generated client locally during development so your IDE can take the hints.
For more on the design guidelines for SDKs in general: https://github.com/dagger/dagger/blob/main/sdk/CONTRIBUTING.md#design-guidelines. A bit further down there's also this breakdown on building the (codegen) client.
I was thinking some form of Hamcrest style builder might be useful, but then I quickly remembered all the loathing I have with hamcrest at times. Plus, you're kinda back in the world of code-gen, which (and I think I saw this mentioned somewhere else) if the code-gen was all handled by a module itself, could just emit a single .java for example, with such matchers.
At least looking at the java stuff (my primarily language) IDE integration would be kinda tricky - as you don't want the dependencies of the pipeline to infect/alter the dependencies of the project.