Skip to content

Commit 7fddbd9

Browse files
feat: cleaned up schema wrapper
1 parent 60318b4 commit 7fddbd9

File tree

14 files changed

+69
-77
lines changed

14 files changed

+69
-77
lines changed

docs/concepts/transforms.rst

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

106106
.. code-block:: python
107107
108-
import msgspec
109108
from typing import Optional
110109
from taskgraph.transforms.base import TransformSequence
111110
from taskgraph.util.schema import Schema
112111
113-
class MySchema(msgspec.Struct, kw_only=True):
112+
class MySchema(Schema):
114113
foo: str # Required field
115114
bar: Optional[bool] = None # Optional field
116115
117116
transforms = TransformSequence()
118-
transforms.add_validate(Schema(MySchema))
117+
transforms.add_validate(MySchema)
119118
120119
In the above example, we can be sure that every task dict has a string field
121120
called ``foo``, and may or may not have a boolean field called ``bar``.

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,16 @@ comments for explanations):
136136

137137
.. code-block:: python
138138
139-
import msgspec
140139
from typing import Optional
141140
from taskgraph.util.schema import Schema
142141
from taskgraph.transforms.base import TransformSequence
143142
144-
# Define the schema using msgspec for better type checking and performance.
145-
class HelloDescriptionSchema(msgspec.Struct, kw_only=True):
143+
# Define the schema using Schema base class for better type checking and performance.
144+
class HelloDescriptionSchema(Schema):
146145
text: str # Required field
147146
description: Optional[str] = None # Optional field
148147
149-
hello_description_schema = Schema(HelloDescriptionSchema)
148+
hello_description_schema = HelloDescriptionSchema
150149
151150
# Create a 'TransformSequence' instance. This class collects transform
152151
# functions to run later.

src/taskgraph/transforms/chunking.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
import msgspec
88

99
from taskgraph.transforms.base import TransformSequence
10+
from taskgraph.util.schema import Schema
1011
from taskgraph.util.templates import substitute
1112

1213

13-
class ChunkConfig(msgspec.Struct, kw_only=True, rename="kebab"):
14+
class ChunkConfig(Schema):
1415
"""
1516
`chunk` can be used to split one task into `total-chunks`
1617
tasks, substituting `this_chunk` and `total_chunks` into any
@@ -25,7 +26,7 @@ class ChunkConfig(msgspec.Struct, kw_only=True, rename="kebab"):
2526

2627

2728
#: Schema for chunking transforms
28-
class ChunkSchema(msgspec.Struct, kw_only=True, omit_defaults=True):
29+
class ChunkSchema(Schema):
2930
# Optional, so it can be used for a subset of tasks in a kind
3031
chunk: Optional[ChunkConfig] = None
3132
__extras__: Dict[str, Any] = msgspec.field(default_factory=dict)

src/taskgraph/transforms/docker_image.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
import re
88
from typing import Any, Dict, List, Optional
99

10-
import msgspec
11-
1210
import taskgraph
1311
from taskgraph.transforms.base import TransformSequence
1412
from taskgraph.util import json
1513
from taskgraph.util.docker import create_context_tar, generate_context_hash
14+
from taskgraph.util.schema import Schema
1615

1716
logger = logging.getLogger(__name__)
1817

@@ -30,9 +29,7 @@
3029

3130

3231
#: Schema for docker_image transforms
33-
class DockerImageSchema(
34-
msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"
35-
):
32+
class DockerImageSchema(Schema):
3633
"""
3734
Schema for docker_image transforms.
3835
@@ -49,7 +46,10 @@ class DockerImageSchema(
4946
cache: Whether this image should be cached based on inputs.
5047
"""
5148

49+
# Required field first
5250
name: str
51+
52+
# Optional fields
5353
parent: Optional[str] = None
5454
symbol: Optional[str] = None
5555
task_from: Optional[str] = None

src/taskgraph/transforms/fetch.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,22 @@
1717

1818
from ..util import path
1919
from ..util.cached_tasks import add_optimization
20+
from ..util.schema import Schema
2021
from ..util.treeherder import join_symbol
2122
from .base import TransformSequence
2223

2324
CACHE_TYPE = "content.v1"
2425

2526

2627
#: Schema for fetch transforms
27-
class FetchConfig(msgspec.Struct, kw_only=True):
28+
class FetchConfig(Schema, rename=None, omit_defaults=False):
2829
"""Configuration for a fetch task type."""
2930

3031
type: str
3132
# Additional fields handled dynamically by fetch builders
3233

3334

34-
class FetchSchema(msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"):
35+
class FetchSchema(Schema):
3536
"""
3637
Schema for fetch transforms.
3738
@@ -199,7 +200,7 @@ def make_task(config, tasks):
199200
yield task_desc
200201

201202

202-
class GPGSignatureConfig(msgspec.Struct, kw_only=True, rename="kebab"):
203+
class GPGSignatureConfig(Schema):
203204
"""GPG signature verification configuration."""
204205

205206
# URL where GPG signature document can be obtained. Can contain the
@@ -209,9 +210,7 @@ class GPGSignatureConfig(msgspec.Struct, kw_only=True, rename="kebab"):
209210
key_path: str
210211

211212

212-
class StaticUrlFetchConfig(
213-
msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"
214-
):
213+
class StaticUrlFetchConfig(Schema, rename="kebab"):
215214
"""Configuration for static-url fetch type."""
216215

217216
type: str
@@ -303,7 +302,7 @@ def create_fetch_url_task(config, name, fetch):
303302
}
304303

305304

306-
class GitFetchConfig(msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"):
305+
class GitFetchConfig(Schema):
307306
"""Configuration for git fetch type."""
308307

309308
type: str

src/taskgraph/transforms/from_deps.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@
2020
from taskgraph.transforms.base import TransformSequence
2121
from taskgraph.util.attributes import attrmatch
2222
from taskgraph.util.dependencies import GROUP_BY_MAP, get_dependencies
23-
from taskgraph.util.schema import validate_schema
23+
from taskgraph.util.schema import Schema, validate_schema
2424
from taskgraph.util.set_name import SET_NAME_MAP
2525

2626

2727
# Define FetchEntry for the fetches field
28-
class FetchEntry(msgspec.Struct, kw_only=True, omit_defaults=True):
28+
class FetchEntry(Schema, rename=None):
2929
"""A fetch entry for an artifact."""
3030

3131
artifact: str
3232
dest: Optional[str] = None
3333

3434

35-
class FromDepsConfig(msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"):
35+
class FromDepsConfig(Schema):
3636
"""
3737
Configuration for from-deps transforms.
3838
@@ -94,7 +94,7 @@ def __post_init__(self):
9494

9595

9696
#: Schema for from_deps transforms
97-
class FromDepsSchema(msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"):
97+
class FromDepsSchema(Schema):
9898
"""Schema for from_deps transforms."""
9999

100100
from_deps: FromDepsConfig

src/taskgraph/transforms/matrix.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
import msgspec
1414

1515
from taskgraph.transforms.base import TransformSequence
16+
from taskgraph.util.schema import Schema
1617
from taskgraph.util.templates import substitute_task_fields
1718

1819

19-
class MatrixConfig(msgspec.Struct, kw_only=True, rename="kebab"):
20+
class MatrixConfig(Schema):
2021
"""
2122
Matrix configuration for generating multiple tasks.
2223
"""
@@ -43,7 +44,7 @@ class MatrixConfig(msgspec.Struct, kw_only=True, rename="kebab"):
4344

4445

4546
#: Schema for matrix transforms
46-
class MatrixSchema(msgspec.Struct, kw_only=True, omit_defaults=True):
47+
class MatrixSchema(Schema):
4748
name: str
4849
matrix: Optional[MatrixConfig] = None
4950
__extras__: Dict[str, Any] = msgspec.field(default_factory=dict)

src/taskgraph/transforms/notify.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import msgspec
1414

1515
from taskgraph.transforms.base import TransformSequence
16-
from taskgraph.util.schema import resolve_keyed_by
16+
from taskgraph.util.schema import Schema, resolve_keyed_by
1717

1818
StatusType = Literal[
1919
"on-completed",
@@ -26,31 +26,31 @@
2626
]
2727

2828

29-
class EmailRecipient(msgspec.Struct, kw_only=True, rename="kebab"):
29+
class EmailRecipient(Schema):
3030
"""Email notification recipient."""
3131

3232
type: Literal["email"]
3333
address: Union[str, Dict[str, Any]] # Can be keyed-by
3434
status_type: Optional[StatusType] = None
3535

3636

37-
class MatrixRoomRecipient(msgspec.Struct, kw_only=True, rename="kebab"):
37+
class MatrixRoomRecipient(Schema):
3838
"""Matrix room notification recipient."""
3939

4040
type: Literal["matrix-room"]
4141
room_id: str
4242
status_type: Optional[StatusType] = None
4343

4444

45-
class PulseRecipient(msgspec.Struct, kw_only=True, rename="kebab"):
45+
class PulseRecipient(Schema):
4646
"""Pulse notification recipient."""
4747

4848
type: Literal["pulse"]
4949
routing_key: str
5050
status_type: Optional[StatusType] = None
5151

5252

53-
class SlackChannelRecipient(msgspec.Struct, kw_only=True, rename="kebab"):
53+
class SlackChannelRecipient(Schema):
5454
"""Slack channel notification recipient."""
5555

5656
type: Literal["slack-channel"]
@@ -71,22 +71,22 @@ class SlackChannelRecipient(msgspec.Struct, kw_only=True, rename="kebab"):
7171
"""Map each type to its primary key that will be used in the route."""
7272

7373

74-
class EmailLink(msgspec.Struct, kw_only=True):
74+
class EmailLink(Schema, rename=None, omit_defaults=False):
7575
"""Email link configuration."""
7676

7777
text: str
7878
href: str
7979

8080

81-
class EmailContent(msgspec.Struct, kw_only=True, omit_defaults=True):
81+
class EmailContent(Schema, rename=None):
8282
"""Email notification content."""
8383

8484
subject: Optional[str] = None
8585
content: Optional[str] = None
8686
link: Optional[EmailLink] = None
8787

8888

89-
class MatrixContent(msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"):
89+
class MatrixContent(Schema):
9090
"""Matrix notification content."""
9191

9292
body: Optional[str] = None
@@ -95,32 +95,30 @@ class MatrixContent(msgspec.Struct, kw_only=True, omit_defaults=True, rename="ke
9595
msg_type: Optional[str] = None
9696

9797

98-
class SlackContent(msgspec.Struct, kw_only=True, omit_defaults=True):
98+
class SlackContent(Schema, rename=None):
9999
"""Slack notification content."""
100100

101101
text: Optional[str] = None
102102
blocks: Optional[List[Any]] = None
103103
attachments: Optional[List[Any]] = None
104104

105105

106-
class NotifyContent(msgspec.Struct, kw_only=True, omit_defaults=True):
106+
class NotifyContent(Schema, rename=None):
107107
"""Notification content configuration."""
108108

109109
email: Optional[EmailContent] = None
110110
matrix: Optional[MatrixContent] = None
111111
slack: Optional[SlackContent] = None
112112

113113

114-
class NotifyConfig(msgspec.Struct, kw_only=True, omit_defaults=True):
114+
class NotifyConfig(Schema, rename=None):
115115
"""Modern notification configuration."""
116116

117117
recipients: List[Dict[str, Any]] # Will be validated as Recipient union
118118
content: Optional[NotifyContent] = None
119119

120120

121-
class LegacyNotificationsConfig(
122-
msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"
123-
):
121+
class LegacyNotificationsConfig(Schema, rename="kebab"):
124122
"""Legacy notification configuration for backwards compatibility."""
125123

126124
emails: Union[List[str], Dict[str, Any]] # Can be keyed-by
@@ -130,9 +128,7 @@ class LegacyNotificationsConfig(
130128

131129

132130
#: Schema for notify transforms
133-
class NotifySchema(
134-
msgspec.Struct, kw_only=True, omit_defaults=True, tag_field="notify_type"
135-
):
131+
class NotifySchema(Schema, tag_field="notify_type"):
136132
"""Schema for notify transforms.
137133
138134
Note: This schema allows either 'notify' or 'notifications' field,

src/taskgraph/transforms/run/toolchain.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@
1818
)
1919
from taskgraph.util import path as mozpath
2020
from taskgraph.util.hash import hash_paths
21+
from taskgraph.util.schema import Schema
2122
from taskgraph.util.shell import quote as shell_quote
2223

2324
CACHE_TYPE = "toolchains.v3"
2425

2526

2627
#: Schema for run.using toolchain
27-
class ToolchainRunSchema(
28-
msgspec.Struct, kw_only=True, omit_defaults=True, rename="kebab"
29-
):
28+
class ToolchainRunSchema(Schema):
3029
"""
3130
Schema for toolchain-script run configuration.
3231
@@ -49,11 +48,14 @@ class ToolchainRunSchema(
4948
workdir: Base work directory used to set up the task.
5049
"""
5150

51+
# Required fields first
5252
using: Literal["toolchain-script"]
5353
script: str
5454
sparse_profile: Optional[str] # Can be None to skip sparse profile
5555
toolchain_artifact: str
5656
workdir: str
57+
58+
# Optional fields
5759
arguments: Optional[List[str]] = None
5860
resources: Optional[List[str]] = None
5961
toolchain_alias: Optional[Union[str, List[str]]] = None

0 commit comments

Comments
 (0)