Element Validation¶
SGN provides validators that enforce pad count and naming constraints on elements. Validators catch misconfiguration early — at construction time rather than at runtime.
Available Validators¶
| Validator | Applies to | Constraint |
|---|---|---|
one_to_one |
TransformElement | Exactly one sink pad and one source pad |
one_to_many |
TransformElement | Exactly one sink pad, any number of source pads |
many_to_one |
TransformElement | Any number of sink pads, exactly one source pad |
pad_names_match |
TransformElement | Source and sink pad names are the same set |
num_pads |
TransformElement | Exact counts for sink and/or source pads |
single_pad |
SinkElement | Exactly one sink pad |
All validators are in the sgn.validator module:
Using Validators as Decorators¶
Decorate a validate() method on your element class. The validator runs its
check before your method body executes:
from dataclasses import dataclass
from sgn import TransformElement, validator
@dataclass
class MyTransform(TransformElement):
@validator.one_to_one
def validate(self) -> None:
# Additional custom validation can go here
pass
The validate() method is called automatically during element construction.
If the element is instantiated with the wrong number of pads, an
AssertionError is raised immediately.
Using Validators Directly¶
Call the validator in __post_init__() instead of decorating a method. Pass
self as the argument:
from dataclasses import dataclass
from sgn import SinkElement, validator
@dataclass
class MySink(SinkElement):
def __post_init__(self):
super().__post_init__()
validator.single_pad(self)
Both approaches produce the same result — choose whichever fits your style.
Specifying Exact Pad Counts¶
num_pads takes keyword arguments for sink_pads and source_pads. Either
can be omitted to leave that side unconstrained:
@dataclass
class MergeTransform(TransformElement):
@validator.num_pads(sink_pads=2, source_pads=1)
def validate(self) -> None:
pass
When used directly, num_pads returns a validator that you then call with
the instance:
def __post_init__(self):
super().__post_init__()
validator.num_pads(sink_pads=2, source_pads=1)(self)
Matching Pad Names¶
pad_names_match asserts that the set of source pad names equals the set of
sink pad names. This is useful for pass-through transforms that process each
channel independently:
@dataclass
class PerChannelTransform(TransformElement):
@validator.pad_names_match
def validate(self) -> None:
pass
# OK — pad names match
t = PerChannelTransform(name="t", sink_pad_names=["H1", "L1"], source_pad_names=["H1", "L1"])
# AssertionError — pad names don't match
t = PerChannelTransform(name="t", sink_pad_names=["H1"], source_pad_names=["H1", "L1"])
Combining Validators¶
Stack multiple decorators or chain direct calls to apply more than one constraint: