composite strategy doesn't work as planned

65 views Asked by At

trying to create a rather complex strategy using python's Hypothesis doesn't work as planned. the strategy is a fixed_dictionaries (recursive_strategy) where some of the dictioneries 'values' are actually dependent on each other.

i tried to add composite to add the dependency, but for some reason now i'm getting the following error:

TypeError: 'LazyStrategy' object is not subscriptable

this is how my code looks like

from classes import Example
from hypothesis import given, strategies as st
import re

MAX_DEPTH =3
all_types = ['a','b','c','d']
@st.composite
def recursive_Example_strategy(draw,depth=0):
    value_strategies = {type_name: st.from_regex(r'^(?:[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*)?',fullmatch=True) for type_name in all_types}
    value_strategies['b'] = st.text(st.integers())
    type_ = draw(st.sampled_from(all_types))
    value_strategy = value_strategies[type_]
    example_type_strategy = st.just(type_)
    if depth >= MAX_DEPTH:
        return st.fixed_dictionaries({
            "type": example_type_strategy,
            "value": value_strategy,
            "operands": st.none(),
            })
    else:
        return st.fixed_dictionaries({
            "type": example_type_strategy,
            "value": value_strategy,
            "operands": st.lists(st.deferred(lambda: recursive_Example_strategy(depth + 1)), max_size=3),
            })
            
@given(Example_dict=recursive_Example_strategy())
def test_get_value(Example_dict):
    example = Example(Example_dict['type'])
    example.update_from_dict(Example_dict)
    if example.type == 'a':
        assert example.get_int_value() == int(Example_dict['value'])
    elif example.type == 'b':
        assert int(re.sub(r'.*\((\d+)\).*', r'\1', Example_dict['value']))

i tried to run it and got the error. worth mentioning that before i've added 'composite' it worked fine (with @given(Example_dict=recursive_Example_strategy)

in addition i tried to run separately the 'composite' part, as a different method, and pass it as a @given, but i got an error stating i cannot add 'composite' to a method with default parameters.

1

There are 1 answers

0
Zac Hatfield-Dodds On

Your @composite strategy should return values, not strategies. Try return draw(st.fixed_dictionaries(...)).