Utilities
Helper functions and utilities for normalization, value providers, and parameter injection.
Normalization
Section titled “Normalization”Utilities for normalizing strings and data structures using Unicode normalization forms.
Module: giskard.checks.utils.normalization
normalize_string
Section titled “normalize_string”Normalize a string using a specified Unicode normalization form.
from giskard.checks.utils.normalization import normalize_string
# NFC normalization (canonical composition)text = "café" # with combining accentnormalized = normalize_string(text, normalization_form="NFC")
# NFD normalization (canonical decomposition)normalized = normalize_string(text, normalization_form="NFD")
# NFKC normalization (compatibility composition)normalized = normalize_string(text, normalization_form="NFKC")
# NFKD normalization (compatibility decomposition)normalized = normalize_string(text, normalization_form="NFKD")Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
value | str | required | String to normalize |
normalization_form | Literal['NFC', 'NFD', 'NFKC', 'NFKD'] | None | None | Unicode normalization form |
Returns:
str: Normalized string
normalize_data
Section titled “normalize_data”Recursively normalize all strings in a dictionary or list.
from giskard.checks.utils.normalization import normalize_data
# Normalize nested data structuredata = { "name": "café", "items": ["naïve", "résumé"], "details": { "city": "São Paulo" }}
normalized_data = normalize_data(data, normalization_form="NFC")Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
data | T (dict or list) | required | Data structure to normalize |
normalization_form | Literal['NFC', 'NFD', 'NFKC', 'NFKD'] | None | None | Unicode normalization form |
Returns:
T: Data structure with normalized strings
Normalization Forms
Section titled “Normalization Forms”| Form | Description | Use Case |
|---|---|---|
NFC | Canonical Composition | Most common; combines characters |
NFD | Canonical Decomposition | Separates base + combining characters |
NFKC | Compatibility Composition | Combines + converts compatibility chars |
NFKD | Compatibility Decomposition | Separates + converts compatibility chars |
Value Providers
Section titled “Value Providers”Abstract value provider patterns for static values and callables.
Module: giskard.checks.utils.value_provider
ValueProvider
Section titled “ValueProvider”Abstract base class for value providers.
from giskard.checks.utils.value_provider import ValueProvider
class CustomProvider(ValueProvider): """Custom value provider implementation."""
async def provide(self, *args, **kwargs): # Custom logic to provide value return computed_valueStaticValueProvider
Section titled “StaticValueProvider”Provider for static values.
from giskard.checks.utils.value_provider import StaticValueProvider
# Create a static value providerprovider = StaticValueProvider(value="hello")
# Provide the valueresult = await provider.provide() # Returns "hello"Parameters:
| Parameter | Type | Description |
|---|---|---|
value | R | The static value to provide |
CallableValueProvider
Section titled “CallableValueProvider”Provider that wraps a callable with parameter injection.
from giskard.checks.utils.value_provider import CallableValueProviderfrom giskard.checks.utils.parameter_injection import CallableInjectionMapping
def compute_value(x: int, y: int) -> int: return x + y
# Create injection mappingmapping = CallableInjectionMapping.from_callable( compute_value, # Define parameter injections here)
# Create providerprovider = CallableValueProvider( callable=compute_value, injection_mapping=mapping)
# Provide the valueresult = await provider.provide()Parameters:
| Parameter | Type | Description |
|---|---|---|
callable | Callable | Function to call for value |
injection_mapping | CallableInjectionMapping | Parameter injection configuration |
ValueGeneratorProvider
Section titled “ValueGeneratorProvider”Provider for generator-based values.
from giskard.checks.utils.value_provider import ValueGeneratorProvider
async def value_generator(): yield "first" yield "second" yield "third"
provider = ValueGeneratorProvider.from_mapping(value_generator)
# Use the providerasync for value in provider.provide(): print(value)Parameter Injection
Section titled “Parameter Injection”Dynamic parameter injection for callables.
Module: giskard.checks.utils.parameter_injection
CallableInjectionMapping
Section titled “CallableInjectionMapping”Maps parameters to inject into a callable.
from giskard.checks.utils.parameter_injection import CallableInjectionMapping
def my_function(trace, inputs, config): # Function that needs parameters injected return process(trace, inputs, config)
# Create injection mappingmapping = CallableInjectionMapping.from_callable( my_function, # Define which parameters to inject and from where)
# Inject parametersbound_function = mapping.inject_parameters( my_function, trace=current_trace, inputs=current_inputs, config=current_config)
# Call with injected parametersresult = bound_function()Methods:
from_callable(callable, *args_reqs, **kwargs_reqs)
Section titled “from_callable(callable, *args_reqs, **kwargs_reqs)”Create an injection mapping from a callable.
Parameters:
callable: The function to create mapping forargs_reqs: Positional argument injection requirementskwargs_reqs: Keyword argument injection requirements
Returns: CallableInjectionMapping
inject_parameters(value, *args, **kwargs)
Section titled “inject_parameters(value, *args, **kwargs)”Inject parameters into a callable.
Parameters:
value: Callable to inject intoargs: Positional arguments to injectkwargs: Keyword arguments to inject
Returns: Bound callable with injected parameters
ParameterInjection
Section titled “ParameterInjection”Configuration for a single parameter injection.
from giskard.checks.utils.parameter_injection import ParameterInjection
# Create parameter injection configurationinjection = ParameterInjection( name="trace", source="context")Generator Utilities
Section titled “Generator Utilities”Utilities for converting values and generators to async generators.
Module: giskard.checks.utils.generator
a_generator
Section titled “a_generator”Convert a value or generator (sync or async) into an async generator.
from giskard.checks.utils.generator import a_generator
# Convert static value to async generatorasync for value in a_generator("hello"): print(value) # Yields "hello" once
# Convert sync generatordef sync_gen(): yield 1 yield 2 yield 3
async for value in a_generator(sync_gen()): print(value) # Yields 1, 2, 3
# Convert async generator (pass-through)async def async_gen(): yield "a" yield "b"
async for value in a_generator(async_gen()): print(value) # Yields "a", "b"Parameters:
| Parameter | Type | Description |
|---|---|---|
value_or_generator | YieldType | SyncOrAsyncGenerator | Value or generator to convert |
Returns:
AsyncGenerator: Async generator yielding values
Use Cases:
# Normalize different input types to async generatorsasync def process_values(source): async for value in a_generator(source): # Process each value result = transform(value) yield result
# Works with static valuesasync for r in process_values("single value"): print(r)
# Works with listsasync for r in process_values([1, 2, 3]): print(r)
# Works with generatorsasync for r in process_values(my_generator()): print(r)Usage Patterns
Section titled “Usage Patterns”Text Comparison with Normalization
Section titled “Text Comparison with Normalization”from giskard.checks import Check, CheckResult, Tracefrom giskard.checks.utils.normalization import normalize_string
@Check.register("normalized_comparison")class NormalizedComparison(Check): expected: str normalization_form: str = "NFC"
async def run(self, trace: Trace) -> CheckResult: actual = trace.last.outputs
# Normalize both strings expected_norm = normalize_string( self.expected, normalization_form=self.normalization_form ) actual_norm = normalize_string( actual, normalization_form=self.normalization_form )
if expected_norm == actual_norm: return CheckResult.success( message="Strings match after normalization" ) else: return CheckResult.failure( message="Strings don't match", details={ "expected": expected_norm, "actual": actual_norm } )Custom Value Provider
Section titled “Custom Value Provider”from giskard.checks.utils.value_provider import ValueProvider
class DatabaseValueProvider(ValueProvider): """Provide values from a database."""
def __init__(self, query: str, db_connection): self.query = query self.db = db_connection
async def provide(self, **params): # Execute query with parameters result = await self.db.execute(self.query, **params) return result.fetchone()
# Use in testingprovider = DatabaseValueProvider( query="SELECT name FROM users WHERE id = :user_id", db_connection=db)
# Get valueuser_name = await provider.provide(user_id=123)See Also
Section titled “See Also”- Core API - Core types and base classes
- Built-in Checks - Checks using normalization
- Generators - Input generators