Skip to content

Commit d6f3589

Browse files
feat: updated some bugs
1 parent de18fdf commit d6f3589

File tree

5 files changed

+42
-31
lines changed

5 files changed

+42
-31
lines changed

docs/concepts/transforms.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,17 @@ about the state of the tasks at given points. Here is an example:
105105

106106
.. code-block:: python
107107
108+
import msgspec
109+
from typing import Optional
108110
from taskgraph.transforms.base import TransformSequence
109-
from taskgraph.util.schema import Optional, Required, Schema
111+
from taskgraph.util.schema import Schema
110112
111-
my_schema = Schema({
112-
Required("foo"): str,
113-
Optional("bar"): bool,
114-
})
113+
class MySchema(msgspec.Struct, kw_only=True):
114+
foo: str # Required field
115+
bar: Optional[bool] = None # Optional field
115116
116-
transforms.add_validate(my_schema)
117+
transforms = TransformSequence()
118+
transforms.add_validate(Schema(MySchema))
117119
118120
In the above example, we can be sure that every task dict has a string field
119121
called ``foo``, and may or may not have a boolean field called ``bar``.

docs/tutorials/creating-a-task-graph.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,17 @@ comments for explanations):
136136

137137
.. code-block:: python
138138
139-
from taskgraph.util.schema import Optional, Required, Schema
139+
import msgspec
140+
from typing import Optional
141+
from taskgraph.util.schema import Schema
140142
from taskgraph.transforms.base import TransformSequence
141143
142-
# Define the schema. We use our schema validation to ensure correctness.
143-
hello_description_schema = Schema({
144-
Required("text"): str,
145-
Optional("description"): str,
146-
})
144+
# Define the schema using msgspec for better type checking and performance.
145+
class HelloDescriptionSchema(msgspec.Struct, kw_only=True):
146+
text: str # Required field
147+
description: Optional[str] = None # Optional field
148+
149+
hello_description_schema = Schema(HelloDescriptionSchema)
147150
148151
# Create a 'TransformSequence' instance. This class collects transform
149152
# functions to run later.

src/taskgraph/transforms/run/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ class FetchesSchema(msgspec.Struct, kw_only=True, rename="kebab", omit_defaults=
3434

3535
artifact: str
3636
dest: TOptional[str] = None
37-
extract: bool = True
38-
verify_hash: bool = True
37+
extract: bool = False
38+
verify_hash: bool = False
3939

4040

4141
# When configuration using msgspec

src/taskgraph/transforms/task.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
from taskgraph.util.hash import hash_path
2727
from taskgraph.util.keyed_by import evaluate_keyed_by
2828
from taskgraph.util.schema import (
29-
Optional,
30-
Required,
3129
Schema,
3230
resolve_keyed_by,
3331
validate_schema,
@@ -200,18 +198,23 @@ def payload_builder(name, schema):
200198
"""
201199
Decorator for registering payload builders.
202200
203-
Supports both dict schemas and msgspec.Struct types.
201+
Requires msgspec.Struct schema types for type safety and performance.
204202
"""
205-
# Handle msgspec schemas
206-
if isinstance(schema, type) and issubclass(schema, msgspec.Struct):
207-
# Wrap msgspec schema in our compatibility Schema class
208-
schema = Schema(schema)
209-
else:
210-
# Traditional dict schema - extend it with required fields
211-
schema = Schema({Required("implementation"): name, Optional("os"): str}).extend(
212-
schema
203+
# Ensure we're using msgspec schemas
204+
if not (isinstance(schema, type) and issubclass(schema, msgspec.Struct)):
205+
raise TypeError(
206+
f"payload_builder requires msgspec.Struct schema, got {type(schema).__name__}. "
207+
f"Please migrate to msgspec: class {name.title()}Schema(msgspec.Struct): ..."
213208
)
214209

210+
# Verify the schema has required fields
211+
fields = {f.name for f in msgspec.structs.fields(schema)}
212+
if "implementation" not in fields:
213+
raise ValueError(f"Schema for {name} must include 'implementation' field")
214+
215+
# Wrap msgspec schema in our compatibility Schema class
216+
schema = Schema(schema)
217+
215218
def wrap(func):
216219
assert name not in payload_builders, f"duplicate payload builder name {name}"
217220
payload_builders[name] = PayloadBuilder(schema, func) # type: ignore

template/{{cookiecutter.project_name}}/taskcluster/{{cookiecutter.project_slug}}_taskgraph/transforms/hello.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import msgspec
2+
13
from taskgraph.transforms.base import TransformSequence
2-
from taskgraph.util.schema import Required, Schema
4+
from taskgraph.util.schema import Schema
5+
6+
7+
class HelloSchema(msgspec.Struct, kw_only=True):
8+
noun: str # Required field
9+
310

4-
HELLO_SCHEMA = Schema(
5-
{
6-
Required("noun"): str,
7-
}
8-
)
11+
HELLO_SCHEMA = Schema(HelloSchema)
912

1013
transforms = TransformSequence()
1114
transforms.add_validate(HELLO_SCHEMA)

0 commit comments

Comments
 (0)