Skip to content

@W-19976108: Implement Faker and Plugin Validations#1105

Merged
vsbharath merged 1 commit into
W-19976091/jinja-validationfrom
W-19976108/plugin-faker-validations
Nov 7, 2025
Merged

@W-19976108: Implement Faker and Plugin Validations#1105
vsbharath merged 1 commit into
W-19976091/jinja-validationfrom
W-19976108/plugin-faker-validations

Conversation

@aditya-balachander
Copy link
Copy Markdown
Contributor

🎯 Overview

This PR adds semantic validation for Faker provider calls and three core plugins (Counters, UniqueId, and StatisticalDistributions). Users now get immediate feedback on invalid Faker methods, incorrect parameters, and plugin configuration errors—all before data generation begins.

Note: This PR implements validation for 3 out of 11+ plugins in Snowfakery. The remaining plugins (Math, Schedule, DateTime, etc.) do not yet have validators and will be addressed in future PRs. The pattern established here makes it straightforward to add validators for other plugins.

✨ What's New

1. Faker Method Validation (Introspection-Based)

Added FakerValidators class that uses Python's inspect module to validate Faker provider calls:

  • Provider name validation - Catches typos with suggestions (e.g., "Did you mean first_name?")
  • Parameter validation - Verifies parameter names and counts using signature introspection
  • Type checking - Validates parameter types when type annotations are available

Example:

- object: Person
  fields:
    # ❌ Error: Unknown Faker provider 'frist_name'. Did you mean 'first_name'?
    name: ${{fake.frist_name()}}
    
    # ❌ Error: fake.email: unexpected keyword argument 'mattching'
    email: ${{fake.email(mattching=True)}}

2. Plugin Validators

Counters Plugin

NumberCounter(start=1, step=1, name=None, parent=None)

Errors (❌):

  • start must be an integer
  • step must be an integer
  • step cannot be zero

Warnings (⚠️):

  • name should be a string (type mismatch)
  • Unknown parameters detected

DateCounter(start_date, step, name=None, parent=None)

Errors (❌):

  • Missing required parameter start_date
  • Missing required parameter step
  • start_date must be parseable as a date
  • step must be a string
  • step format invalid (expects +/-<number><unit> like +1d, -1w, +1M, +1y)

Warnings (⚠️):

  • name should be a string (type mismatch)
  • Unknown parameters detected

UniqueId Plugin

NumericIdGenerator(template=None)

Errors (❌):

  • template must be a string
  • Invalid template parts (only pid, context, index, or numeric values allowed)

Warnings (⚠️):

  • Unknown parameters detected

AlphaCodeGenerator(template, alphabet, min_chars, randomize_codes)

Errors (❌):

  • Invalid template parts (only pid, context, index, or numeric values allowed)
  • alphabet must be a string
  • alphabet must have at least 2 characters
  • alphabet too small for randomization (needs at least 6 chars when randomize_codes=True)
  • min_chars must be an integer
  • min_chars must be positive
  • randomize_codes must be a boolean

Warnings (⚠️):

  • Unknown parameters detected

StatisticalDistributions Plugin

Common to all distributions:

  • Errors (❌): seed must be an integer (if provided)
  • Warnings (⚠️): Unknown parameters detected

normal(loc=0.0, scale=1.0, seed=None)

Errors (❌):

  • loc must be numeric (int or float)
  • scale must be numeric (int or float)
  • scale must be positive

lognormal(mean=0.0, sigma=1.0, seed=None)

Errors (❌):

  • mean must be numeric (int or float)
  • sigma must be numeric (int or float)
  • sigma must be positive

binomial(n, p, seed=None)

Errors (❌):

  • Missing required parameter n
  • Missing required parameter p
  • n must be an integer
  • n must be positive
  • p must be numeric (int or float)
  • p must be between 0.0 and 1.0

exponential(scale=1.0, seed=None)

Errors (❌):

  • scale must be numeric (int or float)
  • scale must be positive

poisson(lam, seed=None)

Errors (❌):

  • Missing required parameter lam
  • lam must be numeric (int or float)
  • lam must be positive

gamma(shape, scale, seed=None)

Errors (❌):

  • Missing required parameter shape
  • Missing required parameter scale
  • shape must be numeric (int or float)
  • shape must be positive
  • scale must be numeric (int or float)
  • scale must be positive

🔍 Implementation Highlights

Introspection-Based Validation

The Faker validator uses Python's inspect.signature() to automatically validate any Faker provider without manual maintenance:

# Automatically validates parameter names, counts, and types
sig = inspect.signature(faker_instance.email)
bound = sig.bind(*args, **kwargs)  # Raises TypeError if invalid

This approach scales automatically as Faker providers are updated or added.

Co-located Validators

Validators live alongside their runtime implementations following the established pattern:

class Counters(SnowfakeryPlugin):
    class Functions:
        def NumberCounter(self, start=1, step=1, ...):
            # Runtime implementation
            
    class Validators:
        @staticmethod
        def validate_NumberCounter(sv, context):
            # Validation logic

This co-location makes the code easy to discover and maintain.

@aditya-balachander aditya-balachander requested a review from a team as a code owner November 7, 2025 01:45
@vsbharath vsbharath merged commit 8a06966 into W-19976091/jinja-validation Nov 7, 2025
14 of 16 checks passed
@vsbharath vsbharath deleted the W-19976108/plugin-faker-validations branch November 7, 2025 04:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants