Skip to content

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:

from sgn import validator

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:

@dataclass
class StrictTransform(TransformElement):
    @validator.pad_names_match
    @validator.num_pads(sink_pads=2, source_pads=2)
    def validate(self) -> None:
        pass