Guides
Custom Rules Guide
Learn how to write custom deterministic data quality validation rules
Featuresmith is fully extensible. You can easily add your own deterministic rules by extending the BaseRule interface and defining rule parameters.
The BaseRule Interface
All rules must extend BaseRule and implement the following properties and methods:
id: A unique dotted identifier (e.g.,statistical.zero_variance).name: A descriptive rule title.category: Group category (e.g.,quality,statistical,leakage).severity: Finding severity level (e.g.,RuleSeverity.INFO,WARNING, orCRITICAL).evaluate(profile: ProfileResult) -> list[RuleFinding]: Core audit logic.
Custom Rule Implementation
Here is a complete example of a rule to detect numerical columns that have zero standard deviation (constant value columns):
python
from typing import Anyfrom featuresmith.rules.base import BaseRulefrom featuresmith.core.rule_finding import RuleFinding, RuleSeverityfrom featuresmith.core.profile_result import ProfileResultclass ZeroVarianceRule(BaseRule): """Custom rule to detect columns with zero variance.""" def __init__(self, **kwargs: Any) -> None: super().__init__() self.enabled = kwargs.get("enabled", True) @property def id(self) -> str: return "statistical.zero_variance" @property def name(self) -> str: return "Zero Variance Columns" @property def category(self) -> str: return "statistical" @property def severity(self) -> RuleSeverity: return RuleSeverity.WARNING def evaluate(self, profile: ProfileResult) -> list[RuleFinding]: findings = [] for col_name, col_profile in profile.column_profiles.items(): numeric_stats = col_profile.numeric_stats if numeric_stats is not None and numeric_stats.std == 0.0: findings.append( self.create_finding( column_name=col_name, title="Zero Variance Detected", description=f"Column '{col_name}' has standard deviation of 0.0 (no variance).", evidence={"std": 0.0} ) ) return findingsEvaluating Custom Rules
You can instantiate your rule and run it directly in Python:
python
import featuresmith as fsdataset = fs.load("data.csv")rule = ZeroVarianceRule()# Run rule directly against computed statistical profilesprofile = fs.profile(dataset)findings = rule.evaluate(profile)for finding in findings: print(f"[{finding.severity}] {finding.title} in {finding.column_name}")