Source code for swaggerconformance.strategies.basestrategies

"""
Extra hypothesis strategies built from those in `hypothesis.strategies`, and
helper functions for merging dictionary type strategies and dictionaries of
strategies.
"""
import logging
import datetime
import io

import hypothesis.strategies as hy_st

__all__ = ["json", "dates", "times", "datetimes", "file_objects", "files",
           "merge_dicts_strategy", "merge_dicts_max_size_strategy",
           "merge_optional_dict_strategy"]


log = logging.getLogger(__name__)


[docs]def json(value_limit=5): """Hypothesis strategy for generating values that can be passed to `json.dumps` to produce valid JSON data. :param value_limit: A limit on the number of values in the JSON data - setting this too high can cause value generation to time out. :type value_limit: int """ return hy_st.recursive( hy_st.floats() | hy_st.booleans() | hy_st.text() | hy_st.none(), lambda children: hy_st.dictionaries(hy_st.text(), children), max_leaves=value_limit)
[docs]def dates(): """Hypothesis strategy for generating `datetime.date` values.""" return hy_st.builds( datetime.date.fromordinal, hy_st.integers(min_value=1, max_value=datetime.date.max.toordinal()))
[docs]def times(): """Hypothesis strategy for generating `datetime.time` values.""" return hy_st.builds( datetime.time, hour=hy_st.integers(min_value=0, max_value=23), minute=hy_st.integers(min_value=0, max_value=59), second=hy_st.integers(min_value=0, max_value=59), microsecond=hy_st.integers(min_value=0, max_value=999999))
[docs]def datetimes(): """Hypothesis strategy for generating `datetime.datetime` values.""" return hy_st.builds(datetime.datetime.combine, dates(), times())
[docs]def file_objects(): """Hypothesis strategy for generating pre-populated `file objects`.""" return hy_st.builds(io.BytesIO, hy_st.binary())
[docs]def files(): """Hypothesis strategy for generating objects pyswagger can use as file handles to populate `file` format parameters. Generated values take the format: `dict('data': <file object>)`""" return file_objects().map(lambda x: {'data': x})
[docs]def merge_dicts_strategy(dict_strat_1, dict_strat_2): """Strategy merging two strategies producting dicts into one.""" return hy_st.builds(lambda x, y: dict((list(x.items()) + list(y.items()))), dict_strat_1, dict_strat_2)
[docs]def merge_optional_dict_strategy(required_fields, optional_fields): """Combine dicts of strings mapping to required and optional strategies. :param required_fields: Mapping containing required fields. :type required_fields: dict(str) :param optional_fields: Mapping containing optional fields. :type optional_fields: dict(str) """ # Create a strategy for a set of keys from the optional dict strategy, then # a strategy to build those back into a dictionary. # Finally, merge the strategy of selected optionals with the required one. opt_keys = hy_st.sets(hy_st.sampled_from(list(optional_fields.keys()))) selected_optionals = hy_st.builds( lambda dictionary, keys: {key: dictionary[key] for key in keys}, hy_st.fixed_dictionaries(optional_fields), opt_keys) result = merge_dicts_strategy(hy_st.fixed_dictionaries(required_fields), selected_optionals) return result
[docs]def merge_dicts_max_size_strategy(dict1, dict2, max_size): """Combine dict strategies into one to produce a dict up to a max size. Assumes both dicts have distinct keys. :param max_size: Maximum number of keys in dicts generated by the strategy. :type max_size: int """ # This is grim, but combine both dictionaries after creating a copy of the # second containing a reduced number of keys if that would take us over the # max size. result = hy_st.builds( lambda x, y: dict((list(x.items()) + list(y.items()))[:max_size]), dict1, dict2) return result