Reference

Validators Reference

Every built-in OpenHTF measurement validator — in_range, within_percent, equals, matches_regex, all_in_range, all_equals, dimension_pivot_validate, consistent_end_dimension_pivot_validate — with marginal limits, custom validators and how they appear in the record.

Last updated · Verified with OpenHTF 1.6.1

A validator is a callable that takes the measured value and returns True (PASS) or False (FAIL). Built-ins live in openhtf.util.validators and are also exposed as chainable methods on htf.Measurement.in_range(0, 10) is .with_validator(validators.in_range(0, 10)).

main.py
import openhtf as htf
from openhtf.util import validators

@htf.measures(
    htf.Measurement("vbat").in_range(3.5, 4.2),                    # method form
    htf.Measurement("fw").matches_regex(r"^1\.4\.\d+$"),
    htf.Measurement("ok").equals(True),
    htf.Measurement("ripple", validators=[validators.in_range(maximum=50)]),  # kwargs form
)
def measure(test):
    ...

A measurement may carry several validators; all must pass.

Scalar validators

in_range(minimum=None, maximum=None, marginal_minimum=None, marginal_maximum=None, type=None)

Inclusive numeric range. Either bound may be omitted. marginal_* set inner limits that flag a passing value as marginal. type casts templated string arguments ('{minimum}' filled by with_args). Record string: 3.0 <= x <= 5.0; with marginal limits 5 <= Marginal:9 <= x <= Marginal:11 <= 17; x == 5 when both bounds are equal.

within_percent(expected, percent, marginal_percent=None)

expected ± percent %. within_percent(5.0, 2) accepts 4.9–5.1. Record string: 'x' is within 2% of 5.0. Marginal: None% of 5.0.

equals(value, type=None)

Exact equality for numbers, strings, booleans. Record string: 'x' is equal to '5'.

matches_regex(regex)

re.match against a string value. Record string: 'x' matches /^1\.4/.

with_validator(callable)

Any callable value -> bool. Define __str__ on a class-based validator so the record shows something readable instead of <function <lambda>>.

Validators for lists and dimensioned measurements

all_in_range(minimum, maximum, marginal_minimum=None, marginal_maximum=None)

Every element of a list value is within the range.

all_equals(value, type=None)

Every element of a list value equals value.

dimension_pivot_validate(sub_validator)

Apply a scalar validator to every stored value of a multi-dimensional measurement. Fails if any sample fails. This is the way to put limits on a monitor's time series. Record string: All values pass: 0.3 <= x <= 0.5.

consistent_end_dimension_pivot_validate(sub_validator)

Like dimension_pivot_validate, but once a row passes every following row must pass — models a value that must settle and stay settled (a rail reaching regulation, a temperature reaching set point). Record string: Once pass, rest must also pass: ....

main.py
import openhtf as htf
from openhtf.core import monitors
from openhtf.util import units, validators

def read_current(test):
    return 0.42

@monitors.monitors("current", read_current, units=units.AMPERE, poll_interval_ms=100)
@htf.measures(
    htf.Measurement("current").dimension_pivot_validate(validators.in_range(0.3, 0.5))
)
def load_test(test):
    import time; time.sleep(1)

Marginal limits

in_range and within_percent accept inner marginal bounds. A value between the marginal and hard limits passes but sets marginal: true on the measurement, phase and test, and the console banner shows PASS (MARGINAL). Use it to catch drift before it becomes yield loss. Marginal →

htf.Measurement("resistance").in_range(minimum=5, maximum=17, marginal_minimum=9, marginal_maximum=11)

Conditional validators

.validate_on({DiagResult: validator}) swaps in a different validator when a diagnosis is present — for example a wider current limit in high-power mode.

Custom validators

For anything reusable, subclass ValidatorBase and give it a __str__:

validators_ext.py
from openhtf.util import validators

class Monotonic(validators.ValidatorBase):
    """Every sample of a dimensioned value is >= the previous one."""

    def __call__(self, dim_value):
        samples = [row[-1] for row in dim_value.value]
        return all(b >= a for a, b in zip(samples, samples[1:]))

    def __str__(self):
        return "'x' is monotonically increasing"
htf.Measurement("ramp").with_dimensions(units.SECOND).with_validator(Monotonic())

Validators must be deepcopy()-able (phases are copied when templated with with_args), so avoid holding open file handles or sockets in them. Registering with validators.register(Monotonic, name='monotonic') additionally enables the method form .monotonic().

In the record

Validators are serialized with str():

"supply_voltage": {
  "outcome": "PASS",
  "validators": ["3.2 <= x <= 3.4"],
  "measured_value": 3.31
}

Tools that parse limits back out of the record (including TofuPilot) rely on the built-in formats above — one more reason to prefer built-ins and readable __str__ on custom ones.

On this page

First-pass yield
0%4.1
Track with TofuPilot