minigun.specify module

Property Specification and Test Execution Engine

This module provides the core DSL for property-based testing specification and the execution engine for running tests. It implements the @prop decorator system, test specification composition, and counterexample search coordination.

Key Components:
  • @prop decorator: Define properties with automatic type inference

  • @context decorator: Explicit domain specification for parameters

  • Spec composition: conj(), disj(), impl(), neg() for logical operations

  • check(): Main test execution function with reporter integration

Test Execution Flow:
  1. Calibration phase: Measure timing for budget allocation

  2. Execution phase: Run tests with allocated attempts

  3. Shrinking: Find minimal counterexamples on failure

  4. Reporting: Rich console output with progress and results

The module integrates with the reporter system for sophisticated output including cardinality analysis, budget allocation, and performance metrics.

Example:

from minigun.specify import prop, context, check, conj
import minigun.domain as d

@prop("list length distributes over concatenation")
def test_list_length(xs: list[int], ys: list[int]):
    return len(xs + ys) == len(xs) + len(ys)

@context(d.list(d.int(), 0, 10))
@prop("sorted lists remain sorted after append")
def test_sorted_append(xs: list[int]):
    return xs == sorted(xs) if len(xs) <= 1 else True

# Run conjunction of tests
success = check(conj(test_list_length, test_sorted_append))
class minigun.specify.Spec

Representation of a specification.

minigun.specify.prop(desc)

Decorator for property specfications.

Parameters:

desc (str) – A description of the decorated law.

Returns:

A property specification.

Return type:

Spec

minigun.specify.neg(spec)

A constructor for the negation of a specfication.

Parameters:

spec (Spec) – Term to be negated.

Returns:

A negation of a specification.

Return type:

Spec

minigun.specify.conj(*specs)

A constructor for the conjunction of specfications.

Parameters:

specs (Spec) – Terms of the conjunction.

Returns:

A conjunction of specifications.

Return type:

Spec

minigun.specify.disj(*specs)

A constructor for the disjunction of specfications.

Parameters:

specs (Spec) – Terms of the disjunction.

Returns:

A disjunction of specifications.

Return type:

Spec

minigun.specify.impl(premise, conclusion)

A constructor for the implication of two specfications.

Parameters:
  • premise (Spec) – The premise of the implication.

  • conclusion (Spec) – The conclusion of the implication.

Returns:

A conjunction of specifications.

Return type:

Spec

minigun.specify.context(*lparams, **kparams)

A decorator for defining domains of a property’s parameters.

Parameters:
  • lparam (tuple[minigun.domain.Domain[Any], …]) – Domains of positional parameters.

  • kparam (dict[str, ‘minigun.domain.Domain[Any]]) – Domains of keyword parameters.

Returns:

A property specification.

Return type:

Spec

minigun.specify.check(spec)

Check an interface against its specification with calibration support.

Parameters:

spec (Spec) – The specification to test against.

Returns:

A boolean value representing whether the interfaces passed testing against their specification.

Return type:

bool

minigun.domain module

class minigun.domain.Domain(generate, print)

A domain datatype over a type T.

Parameters:
  • generate (minigun.generate.Generator[T]) – A generator over a type T.

  • print (minigun.pretty.Printer[T]) – A printer over a type T.

minigun.domain.bool()

A domain for booleans.

Returns:

A domain of bool.

Return type:

Domain[bool]

minigun.domain.small_nat()

A domain for integers n in the range 0 <= n <= 100.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.nat()

A domain for integers n in the range 0 <= n <= 10000.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.big_nat()

A domain for integers n in the range 0 <= n <= 1000000.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.small_int()

A domain for integers n in the range -100 <= n <= 100.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.int()

A domain for integers n in the range -10000 <= n <= 10000.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.big_int()

A domain for integers n in the range -1000000 <= n <= 1000000.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.float()

A domain for floats n in the range -e^15 <= n <= e^15.

Returns:

A domain of float.

Return type:

Domain[float]

minigun.domain.int_range(lower_bound, upper_bound)

A domain for indices i in the range lower_bound <= i <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the sampled value, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the sampled value, must be greater than or equal to lower_bound.

Returns:

A domain of int.

Return type:

Domain[int]

minigun.domain.bounded_str(lower_bound, upper_bound, alphabet)

A domain for strings over a given alphabet with bounded length l in the range lower_bound <= l <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the length of the sampled value, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the length of the sampled value, must be greater than or equal to lower_bound.

  • alphabet (str) – A string representing the alphabet to be sampled from.

Returns:

A domain of str.

Return type:

Domain[str]

minigun.domain.str()

A domain for strings over all printable ascii characters.

Returns:

A domain of str.

Return type:

Domain[str]

minigun.domain.word()

A domain for strings over ascii alphabet characters.

Returns:

A domain of str.

Return type:

Domain[str]

minigun.domain.tuple(*domains)

A domain of tuples over given value generators of type A, B, etc.

Parameters:

domains – Value domains over types A, B, etc. to generate tuple values from.

Returns:

A domain of tuples over types A, B, etc.

Return type:

Domain[tuple[A, B, …]]

minigun.domain.bounded_list(lower_bound, upper_bound, domain, ordered=None)

A domain for lists over a given type T with bounded length l in the range 0 <= lower_bound <= l <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the length of the sampled list, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the length of the sampled list, must be greater than or equal to lower_bound.

  • domain (Domain[T]) – A value domain from which list items are samples.

  • ordering (bool (default: False)) – Flag for whether items of sampled lists should be ordered.

Returns:

A domain of lists over type T.

Return type:

Domain[list[T]]

minigun.domain.list(domain, ordered=None)

A domain for lists over a given type T.

Parameters:
  • domain (Domain[T]) – A value domain from which list items are samples.

  • ordering (bool (default: False)) – Flag for whether items of sampled lists should be ordered`.

Returns:

A domain of lists over type T.

Return type:

Domain[list[T]]

minigun.domain.bounded_dict(lower_bound, upper_bound, key_domain, value_domain)

A domain for dicts over a given key type K and value type V with bounded size s in the range 0 <= lower_bound <= s <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the size of the sampled dict, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the size of the sampled dict, must be greater than or equal to lower_bound.

  • key_domain (Domain[K]) – A key domain from which dict keys are samples.

  • value_domain (Domain[V]) – A value domain from which dict values are samples.

Returns:

A domain of dicts over key type K and value type V.

Return type:

Domain[dict[K, V]]

minigun.domain.dict(key_domain, value_domain)

A domain for dicts over a given key type K and value type V.

Parameters:
  • key_domain (Domain[K]) – A key domain from which dict keys are samples.

  • value_domain (Domain[V]) – A value domain from which dict values are samples.

Returns:

A domain of dicts over key type K and value type V.

Return type:

Domain[dict[K, V]]

minigun.domain.bounded_set(lower_bound, upper_bound, domain)

A domain for sets over a given type T with bounded size s in the range 0 <= lower_bound <= s <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the size of the sampled set, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the size of the sampled set, must be greater than or equal to lower_bound.

  • domain (Domain[T]) – A value domain from which set items are samples.

Returns:

A domain of sets over type T.

Return type:

Domain[set[T]]

minigun.domain.set(domain)

A domain for sets over a given type T.

Parameters:

domain (Domain[T]) – A value domain from which set items are samples.

Returns:

A domain of sets over type T.

Return type:

Domain[set[T]]

minigun.domain.maybe(domain)

A domain of maybe over a given type T.

Parameters:

domain (Domain[T]) – A value domain to map maybe over.

Returns:

A domain of maybe over type T.

Return type:

Domain[returns.maybe.Maybe[T]]

minigun.domain.argument_pack(ordering, domains)

A domain of argument packs over a given set of domains.

Parameters:

domains (dict[str, Domain[Any]]) – A mapping from argument names to value domains.

Returns:

A domain of argument packs over the given domains.

Return type:

Domain[dict[str, Any]]

minigun.generate module

Data Generators and Combinators

This module provides the core data generation system for property-based testing. It implements generators for all Python built-in types and combinators for composing complex data structures with proper shrinking support.

Architecture:
  • Generator[T]: Tuple of (sampler, cardinality) for type T

  • Sample[T]: State-threaded generation with shrinking info

  • Combinators: map, bind, filter, choice for composition

Built-in Generators:
  • Primitives: bool, nat, int, float, char, str

  • Collections: list, dict, set, tuple

  • Utilities: constant, one_of, weighted_choice

The generator system integrates with the cardinality analysis system to provide optimal test attempt allocation based on domain complexity.

Example:

import minigun.generate as g
import minigun.arbitrary as a

# Create generators for custom data
person_gen = g.map(
    lambda name, age: {"name": name, "age": age},
    g.str(),
    g.nat(0, 120)
)

# Sample values
state = a.seed(42)
state, maybe_person = person_gen(state)
minigun.generate.map(func, *generators)

A variadic map function of given input generators over types A, B, etc. to an output generator over type R.

Parameters:
  • func (A x B x … -> R) – A function mapping the input values of type A, B, etc. to an output value of type R.

  • generators (Tuple[Generator[A], Generator[B], …]) – Input generators over types A, B, etc. to map from.

Returns:

A mapped output generator.

Return type:

Generator[R]

minigun.generate.bind(func, card, *generators)

A variadic bind function of given input generators over types A, B, etc. to an output generator over type R.

Parameters:
  • func (A x B x … -> Generator[R]) – A function creating a generator of type R, parameterized by generated instances of type A, B, etc.

  • card (Tuple[Cardinality, …] -> Cardinality) – Cardinality function that computes combined cardinality from input cardinalities

  • generators (Tuple[Generator[B], Generator[C], …]) – Additional generators over types B, C, etc. to instance from.

Returns:

A bound output generator.

Return type:

Generator[R]

minigun.generate.lazy(thunk)

Defer construction of a generator until the first sample is drawn.

Useful for recursive generator definitions where eager construction (including inspect.signature calls and cardinality arithmetic performed by combinators such as map, bind and choice) would otherwise blow up construction time exponentially in the recursion depth. The inner generator is built once and then reused.

Cardinality is reported as Infinite since the inner generator is unknown at construction time; combinators that see this value fall back to their infinite-cardinality strategies.

Parameters:

thunk (() -> Generator[T]) – A zero-argument callable returning a generator of type T.

Returns:

A generator of type T that builds its inner generator on demand.

Return type:

Generator[T]

minigun.generate.filter(predicate, generator)

Filter a generator of type T.

Parameters:
  • predicate (A -> bool) – A predicate on type T.

  • generator (Generator[T]) – A generator of type T to be filtered.

Returns:

A generator of type T.

Return type:

Generator[T]

minigun.generate.constant(value)

A generator that samples a constant value.

Parameters:

value (T) – The constant value to be samples.

Returns:

A constant generator.

Return type:

Generator[T]

minigun.generate.none()

A constant generator for None.

Returns:

A constant generator of None.

Return type:

Generator[None]

minigun.generate.bool()

A generator for booleans.

Returns:

A generator of bool.

Return type:

Generator[bool]

minigun.generate.small_nat()

A generator for integers n in the range 0 <= n <= 100.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.nat()

A generator for integers n in the range 0 <= n <= 10000.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.big_nat()

A generator for integers n in the range 0 <= n <= 1000000.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.small_int()

A generator for integers n in the range -100 <= n <= 100.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.int()

A generator for integers n in the range -10000 <= n <= 10000.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.big_int()

A generator for integers n in the range -1000000 <= n <= 1000000.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.float()

A generator for floats n in the range -e^15 <= n <= e^15.

Returns:

A generator of float.

Return type:

Generator[float]

minigun.generate.int_range(lower_bound, upper_bound)

A generator for indices i in the range lower_bound <= i <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the sampled value, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the sampled value, must be greater than or equal to lower_bound.

Returns:

A generator of int.

Return type:

Generator[int]

minigun.generate.bounded_str(lower_bound, upper_bound, alphabet)

A generator for strings over a given alphabet with bounded length l in the range lower_bound <= l <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the length of the sampled value, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the length of the sampled value, must be greater than or equal to lower_bound.

  • alphabet (str) – A string representing the alphabet to be sampled from.

Returns:

A generator of str.

Return type:

Generator[str]

minigun.generate.str()

A generator for strings over all printable ascii characters.

Returns:

A generator of str.

Return type:

Generator[str]

minigun.generate.word()

A generator for strings over ascii alphabet characters.

Returns:

A generator of str.

Return type:

Generator[str]

minigun.generate.tuple(*generators)

A generator of tuples over given value generators of type A, B, etc.

Parameters:

generators (Tuple[Generator[A], Generator[B], …]) – Value generators over types A, B, etc. to generate tuple values from.

Returns:

A generator of tuples over types A, B, etc.

Return type:

Generator[Tuple[A, B, …]]

minigun.generate.bounded_list(lower_bound, upper_bound, generator, ordered=None)

A generator for lists over a given type T with bounded length l in the range 0 <= lower_bound <= l <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the length of the sampled list, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the length of the sampled list, must be greater than or equal to lower_bound.

  • generator (Generator[T]) – A value generator from which list items are sampled.

  • ordering (bool (default: False)) – Flag for whether items of sampled lists should be ordered.

Returns:

A generator of lists over type T.

Return type:

Generator[List[T]]

minigun.generate.list(generator, ordered=None)

A generator for lists over a given type T.

Parameters:
  • generator (Generator[T]) – A value generator from which list items are sampled.

  • ordering (bool (default: False)) – Flag for whether items of sampled lists should be ordered`.

Returns:

A generator of lists over type T.

Return type:

Generator[List[T]]

minigun.generate.map_list(generators, ordered=None)

Composes lists of generators over a given type T, resulting in a generator of lists over the given type T.

Parameters:
  • generators (List[Generator[T]]) – A list of value generators from which value lists are sampled.

  • ordering (bool (default: False)) – Flag for whether items of sampled lists should be ordered`.

Returns:

A generator of lists over type T.

Return type:

Generator[List[T]]

minigun.generate.list_append(items_gen, item_gen)

Compose a lists generator over type T with a value generator of type T, resulting in a list generator over the given type T, where a value has been sampled from the later generator and guaranteed to have been appended to output sampled lists.

Parameters:
  • items_gen (Generator[List[T]]) – A generator from which lists are sampled.

  • item_gen (Generator[T]) – A generator from which values are sampled.

Returns:

A generator of lists over type T.

Return type:

Generator[List[T]]

minigun.generate.bounded_dict(lower_bound, upper_bound, key_generator, value_generator)

A generator for dicts over a given key type K and value type V with bounded size s in the range 0 <= lower_bound <= s <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the size of the sampled dict, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the size of the sampled dict, must be greater than or equal to lower_bound.

  • key_generator (Generator[K]) – A key generator from which dict keys are sampled.

  • value_generator (Generator[V]) – A value generator from which dict values are sampled.

Returns:

A generator of dicts over key type K and value type V.

Return type:

Generator[Dict[K, V]]

minigun.generate.dict(key_generator, value_generator)

A generator for dicts over a given key type K and value type V.

Parameters:
  • key_generator (Generator[K]) – A key generator from which dict keys are sampled.

  • value_generator (Generator[V]) – A value generator from which dict values are sampled.

Returns:

A generator of dicts over key type K and value type V.

Return type:

Generator[Dict[K, V]]

minigun.generate.map_dict(generators)

Composes dicts of generators over given types K and V, resulting in a generator of dicts over the given types K and V.

Parameters:

generators (Dict[K, Generator[V]]) – A dict of value generators from which value dicts are sampled.

Returns:

A generator of dicts over types K and V.

Return type:

Generator[Dict[K, V]]

minigun.generate.dict_insert(kvs_gen, key_gen, value_gen)

Compose a dict generator over types K and V with a key generator of the given type K and a value generator of the given type V, resulting in a generator of dicts over the types K and V, where a key and value has been sampled from the later generators and guaranteed to have been inserted into the output sampled dicts.

Parameters:
  • kvs_gen (Generator[Dict[K, V]]) – A generator from which dicts are sampled.

  • key_gen (Generator[K]) – A generator from which keys are sampled.

  • value_gen (Generator[V]) – A generator from which values are sampled.

Returns:

A generator of dicts over types K and V.

Return type:

Generator[Dict[K, V]]

minigun.generate.bounded_set(lower_bound, upper_bound, generator)

A generator for sets over a given type T with bounded size s in the range 0 <= lower_bound <= s <= upper_bound.

Parameters:
  • lower_bound (int) – A min bound for the size of the sampled set, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the size of the sampled set, must be greater than or equal to lower_bound.

  • generator (Generator[T]) – A value generator from which set items are sampled.

Returns:

A generator of sets over type T.

Return type:

Generator[Set[T]]

minigun.generate.set(generator)

A generator for sets over a given type T.

Parameters:

generator (Generator[T]) – A value generator from which set items are sampled.

Returns:

A generator of sets over type T.

Return type:

Generator[Set[T]]

minigun.generate.map_set(generators)

Composes sets of generators over a given type T, resulting in a generator of sets over the given type T.

Parameters:

generators (Set[Generator[T]]) – A set of value generators from which value sets are sampled.

Returns:

A generator of sets over type T.

Return type:

Generator[Set[T]]

minigun.generate.set_add(items_gen, item_gen)

Compose a set generator over a type T with a value generator of type T, resulting in a generator of sets over the given type T, where a value has been sampled from the later generator and guaranteed to have been added to the output sampled sets.

Parameters:
  • items_gen (Generator[Set[T]]) – A generator from which sets are sampled.

  • item_gen (Generator[T]) – A generator from which values are sampled.

Returns:

A generator of output sets over type T.

Return type:

Generator[Set[T]]

minigun.generate.maybe(generator)

A generator of maybe over a given type T.

Parameters:

generator (Generator[T]) – A value generator to map maybe over.

Returns:

A generator of maybe over type T.

Return type:

Generator[returns.maybe.Maybe[T]]

minigun.generate.argument_pack(generators)

A generator for argument packs.

Parameters:

generators (Dict[str, Generator[Any]]) – Generator from which the arguments are sampled.

Returns:

A generator for argument packs.

Return type:

Generator[Dict[str, Any]]

minigun.generate.choice(*generators)

A generator of a type T composed of other generators of type T.

Parameters:

generators (Tuple[Generator[T], …]) – generators of type T.

Returns:

A generator of type T.

Return type:

Generator[T]

minigun.generate.weighted_choice(*weighted_generators)

A generator of a type T composed of other weighted generators of type T.

Parameters:

weighted_generators (Tuple[Tuple[int, Generator[T]], …]) – Number of chances to sample from, with their corresponding generators of type T.

Returns:

A generator of type T.

Return type:

Generator[T]

minigun.generate.one_of(values)

A generator of a type T defined over a list of T, which will select one of the values of given list when sampled.

Parameters:

values (List[T]) – A list of values of type T.

Returns:

A generator of type T.

Return type:

Generator[T]

minigun.generate.subset_of(values)

A generator of a type T defined over a list of T, which will select a subset of the values of given set when sampled.

Parameters:

values (Set[T]) – A set of values of type T.

Returns:

A set generator of type T.

Return type:

Generator[Set[T]]

minigun.generate.infer(T)

Infer a generator of type T for a given type T with cardinality-aware optimization.

This function leverages the unified cardinality system to choose appropriate generators based on the complexity of the target type.

Parameters:

T (type) – A type to infer a generator of.

Returns:

A maybe of generator of type T.

Return type:

returns.maybe.Maybe[Generator[T]]

minigun.shrink module

Shrinking Strategies and Algorithms

This module implements the shrinking system that finds minimal counterexamples when properties fail. It provides dissection trees that represent all possible ways to shrink a value while preserving the failure condition.

Architecture:
  • Dissection[T]: Tree structure representing value and shrinking options

  • Trimmer[T]: Function producing stream of smaller values

  • unfold(): Create dissection from multiple trimming strategies

Built-in Shrinking:
  • Primitives: int, float, bool shrinking towards zero/false

  • Collections: list, dict, set shrinking by removal and element shrinking

  • Combinators: map, bind for custom data structure shrinking

The shrinking system is integrated with generators to automatically provide minimal counterexamples without additional user configuration.

Example:

import minigun.shrink as s
import minigun.stream as fs

# Define custom trimmer for non-empty lists
def trim_nonempty_list(lst: list[int]) -> fs.Stream[list[int]]:
    if len(lst) <= 1:
        return fs.empty()
    # Try removing elements
    for i in range(len(lst)):
        yield lst[:i] + lst[i+1:]

# Create dissection with custom shrinking
dissection = s.unfold([1, 2, 3, 4], trim_nonempty_list)
minigun.shrink.head(dissection)

Get dissection head.

Parameters:

dissection (Dissection[T]) – A dissection to get the head from.

Returns:

The head of given dissection.

Return type:

T

minigun.shrink.tail(dissection)

Get dissection tail.

Parameters:

dissection (Dissection[T]) – A dissection to get the tail from.

Returns:

The tail of given dissection.

Return type:

minigun.stream.Stream[Dissection[T]]

minigun.shrink.map(func, *dissections)

A variadic map function of given input dissections over types A, B, etc. to an output dissection over type R.

Parameters:
  • func (A x B x … -> R) – A function mapping the input values of type A, B, etc. to an output value of type R.

  • dissections (tuple[Dissection[A], Dissection[B], …]) – Input dissections over types A, B, etc. to map from.

Returns:

A mapped output dissection.

Return type:

Dissection[R]

minigun.shrink.bind(func, *dissections)

A variadic bind function of given input dissections over types A, B, etc. to an output dissection over type R.

Parameters:
  • func (A x B x … -> Dissection[R]) – A function mapping the input values of type A, B, etc. to an output dissection of type R.

  • dissections (tuple[Dissection[A], Dissection[B], …]) – Input dissections over types A, B, etc. to map from.

Returns:

A bound output dissection.

Return type:

Dissection[R]

minigun.shrink.filter(predicate, dissection)

Filter a dissection of type T.

Parameters:
  • predicate (A -> bool) – A predicate on type T.

  • dissection (Dissection[T]) – A dissection of type T to be filtered.

Returns:

A dissection of type T.

Return type:

Dissection[T]

minigun.shrink.concat(left, right)

Concatenation of two dissects over type T.

Parameters:
  • left (Dissection[T]) – The first dissection to take the concatenation of.

  • right (Dissection[T]) – The second dissection to take the concatenation of.

Returns:

A dissection that is the concatenation of the two give dissects.

Return type:

Dissection[T]

minigun.shrink.prepend(value, dissection)

Prepend a value to a dissection.

Parameters:
  • value (T) – The value to be prepended.

  • dissection (Dissection[T]) – The dissection to be prepended to.

Returns:

The updated dissection containing the given value.

Return type:

Dissection[T]

minigun.shrink.append(dissection, value)

Append a value to a dissection.

Parameters:
  • dissection (Dissection[T]) – The dissection to be appended to.

  • value (T) – The value to be appended.

Returns:

The updated dissection containing the given value.

Return type:

Dissection[T]

minigun.shrink.singleton(value)

A singleton dissection containing a single unshrinkable value.

Parameters:

value (T) – An unshrinkable value.

Returns:

A dissection over the type T.

Return type:

Dissection[T]

minigun.shrink.unfold(value, *trimmers)

Define a dissection of an n-ary dimensional trimmed iteration of a given value.

Parameters:
  • value (T) – The initial value to do a trimmed iteration of.

  • trimmers (Trimmer[T]) – The given trimmers for values of type T.

Returns:

A dissection of trimmed interations over the given value.

Return type:

Dissection[T]

minigun.shrink.int(target)

A shrinker for integers which shrinks towards a given target.

Parameters:

target (int) – A target value to shrink towards.

Returns:

A shrinker of int.

Return type:

Shrinker[T]

minigun.shrink.float(target)

A shrinker for floats which takes a target to shrink towards.

Parameters:

target (float) – A target value to shrink towards.

Returns:

A shrinker of float.

Return type:

Shrinker[float]

minigun.shrink.str()

A shrinker for strings.

Returns:

A shrinker of str.

Return type:

Shrinker[str]

minigun.pretty module

minigun.pretty.bool()

Create a printer for values of type bool.

Returns:

A printer for values of type bool.

Return type:

Printer[bool]

minigun.pretty.int()

Create a printer for values of type int.

Returns:

A printer for values of type int.

Return type:

Printer[int]

minigun.pretty.float(digits=2)

Create a printer for values of type float.

Parameters:

digits (int) – The number of digits to print by the float printer.

Returns:

A printer for values of type float.

Return type:

Printer[float]

minigun.pretty.str()

Create a printer for values of type str.

Returns:

A printer for values of type str.

Return type:

Printer[str]

minigun.pretty.tuple(*printers)

Create a printer of tuples over given value printers of type A, B, etc.

Parameters:

printers (tuple[Printer[A], Printer[B], …]) – Value printers over types A, B, etc. to print tuple values with.

Returns:

A printer of tuples over types A, B, etc.

Return type:

Printer[Tuple[A, B, …]]

minigun.pretty.list(printer)

Create a printer for lists over a given type A.

Parameters:

printer (Printer[T]) – A value printer with which list items are printed.

Returns:

A printer of lists over type A.

Return type:

Printer[List[T]]

minigun.pretty.dict(key_printer, value_printer)

Create a printer for dicts over a given key type K and value type V.

Parameters:
  • key_printer (Printer[K]) – A key printer with which dict keys are printed.

  • value_printer (Printer[V]) – A value printer with which dict values are printed.

Returns:

A printer of dicts over key type K and value type V.

Return type:

Printer[Dict[K, V]]

minigun.pretty.set(printer)

Create a printer for sets over a given type A.

Parameters:

printer – A value printer with which set items are printed.

Returns:

A printer of sets over type A.

Return type:

Printer[Set[T]]

minigun.pretty.maybe(printer)

Create a printer of maybe over a given type A.

Parameters:

printer (Printer[T]) – A value printer with which maybe values are printed.

Returns:

A printer of maybe over type A.

Return type:

Printer[returns.maybe.Maybe[T]]

minigun.pretty.argument_pack(ordering, printers)

Create a printer for argument packs`.

Parameters:
  • ordering (List[str]) – The order of parameters in the argument pack.

  • printers (Dict[str, Printer[Any]]) – Value printers with which arguments are printed.

Returns:

A printer of parameter packs.

Return type:

Printer[Dict[str, Any]]

minigun.pretty.infer(T)

Infer a printer of type T for a given type T.

Parameters:

T (type) – A type to infer a printer of.

Returns:

A maybe of printer of type T.

Return type:

returns.maybe.Maybe[Printer[T]]

minigun.arbitrary module

PRNG State Management and Random Generation

This module provides pure functional random number generation with explicit state threading. It implements the foundation for all random generation in Minigun, ensuring reproducible and deterministic test case generation.

Key Components:
  • State: PRNG state tuple for deterministic generation

  • seed(): Initialize state from optional integer seed

  • Primitive generators: bool, nat, int, float, probability

  • Choice utilities: choice, weighted_choice for selection

The module follows functional programming principles with immutable state and pure functions that explicitly thread PRNG state through computations.

Example:

import minigun.arbitrary as a

# Initialize state
state = a.seed(42)

# Generate values with explicit state threading
state, value1 = a.int(state, 1, 100)
state, value2 = a.bool(state)
state, chosen = a.choice(state, ["a", "b", "c"])
minigun.arbitrary.seed(value=None)

Constructor to seed an initial state for Minigun’s PRNG module.

Parameters:

value (int, optional) – An optional integer to be used as the seed.

Returns:

An initial state for random generation.

Return type:

State

minigun.arbitrary.bool(state)

Generate a random boolean value.

Parameters:

state (State) – A state from which to generate a random value.

Returns:

A tuple of a modified state taken after random generation and a generated random value.

Return type:

Tuple[State, bool]

minigun.arbitrary.nat(state, lower_bound, upper_bound)

Generate a random integer value n in the range 0 <= n <= bound.

Parameters:
  • state (State) – A state from which to generate a random value.

  • lower_bound (int) – A min bound for the generated value, must be greater than or equal to zero, and less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the generated value, must be greater than or equal to the lower_bound.

Returns:

A tuple of a modified state taken after random generation and a generated random value.

Return type:

Tuple[State, int]

minigun.arbitrary.int(state, lower_bound, upper_bound)

Generate a random integer value n in the range lower_bound <= n <= upper_bound.

Parameters:
  • state (State) – A state from which to generate a random value.

  • lower_bound (int) – A min bound for the generated value, must be less than or equal to upper_bound.

  • upper_bound (int) – A max bound for the generated value, must be greater than or equal to lower_bound.

Returns:

A tuple of a modified state taken after random generation and a generated random value.

Return type:

Tuple[State, int]

minigun.arbitrary.probability(state)

Generate a random float value n in the range 0.0 <= n <= 1.0.

Parameters:

state (State) – A state from which to generate a random value.

Returns:

A tuple of a modified state taken after random generation and a generated random value.

Return type:

Tuple[State, float]

minigun.arbitrary.float(state, lower_bound, upper_bound)

Generate a random float value n in the range lower_bound <= n <= upper_bound.

Parameters:
  • state (State) – A state from which to generate a random value.

  • lower_bound (float) – A min bound for the generated value, must be less than or equal to upper_bound.

  • upper_bound (float) – A max bound for the generated value, must be greater than or equal to lower_bound.

Returns:

A tuple of a modified state taken after random generation and a generated random value.

Return type:

tuple[State, float]

minigun.arbitrary.weighted_choice(state, weights, choices)

Select a random item from a list of weighted choices.

Parameters:
  • state (State) – A state from which to generate a random value.

  • choices (List[T]) – A list of items to choose from, must have same length as weights.

  • weights (List[int]) – A list of chances for each item in choices, must have same length as choices.

Returns:

A tuple of a modified state taken after random choice of a random item.

Return type:

tuple[State, T]

minigun.arbitrary.choice(state, choices)

Select a random item from a list of choices.

Parameters:
  • state (State) – A state from which to generate a random value.

  • choices (List[T]) – A list of items to choose from.

Returns:

A tuple of a modified state taken after random choice of a random item.

Return type:

tuple[State, T]

minigun.stream module

Functional Stream Operations

This module provides lazy functional streams for efficient handling of potentially infinite sequences. Streams are used extensively throughout Minigun for shrinking trees, generator composition, and lazy evaluation.

Architecture:
  • Stream[T]: Lazy thunked computation yielding (value, next_stream)

  • Combinators: map, filter, filter_map for stream processing

  • Construction: unfold, singleton, constant, from_list

  • Composition: concat, braid for combining streams

Streams enable memory-efficient processing of large or infinite data sets while maintaining functional purity and composability. They’re particularly important in the shrinking system where they represent trees of shrunk values.

Example:

import minigun.stream as fs

# Create infinite stream of natural numbers
nats = fs.unfold(lambda n: Some((n, n + 1)), 0)

# Transform and take first 10 even numbers
evens = fs.map(lambda x: x * 2, nats)
first_10_evens = fs.to_list(evens, 10)
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
minigun.stream.next(stream)

Get the next head and tail of the stream, if a next head exists.

Parameters:

stream (Stream[T]) – A stream of type T.

Returns:

A tuple of maybe the head of stream and the tail of stream.

Return type:

tuple[returns.maybe.Maybe[T], Stream[T]]

minigun.stream.peek(stream)

Peek the next head of the stream, if a next head exists.

Parameters:

stream (Stream[T]) – A stream of type T.

Returns:

Maybe of the head of the stream.

Return type:

returns.maybe.Maybe[T]

minigun.stream.is_empty(stream)

Check if the stream is empty.

Parameters:

stream (Stream[T]) – A stream of type T.

Returns:

A boolean value.

Return type:

bool

minigun.stream.map(func, *streams)

A variadic map function of given input streams over types A, B, etc. to an output stream over type R.

Parameters:
  • func (A x B x … -> R) – A function mapping the input values of type A, B, etc. to an output value of type R.

  • streams (tuple[Stream[A], Stream[B], …]) – Input streams over types A, B, etc. to map from.

Returns:

A mapped output stream.

Return type:

Stream[R]

minigun.stream.filter(predicate, stream)

Filter a stream of type T.

Parameters:
  • predicate (A -> bool) – A predicate on type T.

  • stream (Stream[T]) – A stream of type T to be filtered.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.filter_map(func, stream)

Filter and map a stream of type T to a type R.

Parameters:
  • func (A -> returns.maybe.Maybe[R]) – A function on type T to a maybe value of type R.

  • stream (Stream[T]) – A stream of type T to be filtered.

Returns:

A stream of type R.

Return type:

Stream[R]

minigun.stream.unfold(func, init)

Create a stream of a type T unfolded from a function over a state of type S.

Parameters:
  • func (S -> returns.maybe.Maybe[tuple[T, S]]) – A function that maybe produces a value of type T over given a state of type S.

  • init (S) – An initial value of type S.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.empty(_dummy=None)

Create an empty stream of type T.

Returns:

An empty stream of type T.

Return type:

Stream[T]

minigun.stream.singleton(value)

Create a stream containing only one value, is empty after that value.

Parameters:

value (T) – A value of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.constant(value)

Create a infinite stream containing a constant value.

Parameters:

value (T) – A value of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.prepend(value, stream)

Prepend a value of type T to a stream of type T.

Parameters:
  • value (T) – A value of type T.

  • stream (Stream[T]) – A stream of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.append(stream, value)

Append a value of type T to a stream of type T.

Parameters:
  • stream (Stream[T]) – A stream of type T.

  • value (T) – A value of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.concat(left, right)

Concatenate two streams of type T.

Parameters:
  • left (Stream[T]) – A stream of type T.

  • right (Stream[T]) – A stream of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.braid(*streams)

Braid multiple streams of type T together into a single stream of type T.

Parameters:

streams (tuple[Stream[T], …]) – Multiple streams of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.from_list(items)

Create a stream of type T from a list of type T.

Parameters:

items (list[T]) – A list of type T.

Returns:

A stream of type T.

Return type:

Stream[T]

minigun.stream.to_list(stream, max_items)

Create a list of type T from a stream of type T.

Parameters:

stream (Stream[T]) – A stream of type T.

Returns:

A list of type T.

Return type:

list[T]