예제 #1
0
def from_attrs_attribute(attrib, target):
    """Infer a strategy from the metadata on an attr.Attribute object."""
    # Try inferring from the default argument.  Note that this will only help
    # the user passed `infer` to builds() for this attribute, but in that case
    # we use it as the minimal example.
    default = st.nothing()
    if isinstance(attrib.default, attr.Factory):
        if not getattr(attrib.default, "takes_self", False):  # new in 17.1
            default = st.builds(attrib.default.factory)
    elif attrib.default is not attr.NOTHING:
        default = st.just(attrib.default)

    # Try inferring None, exact values, or type from attrs provided validators.
    null = st.nothing()  # updated to none() on seeing an OptionalValidator
    in_collections = []  # list of in_ validator collections to sample from
    validator_types = set()  # type constraints to pass to types_to_strategy()
    if attrib.validator is not None:
        validator = attrib.validator
        if isinstance(validator, attr.validators._OptionalValidator):
            null = st.none()
            validator = validator.validator
        if isinstance(validator, attr.validators._AndValidator):
            vs = validator._validators
        else:
            vs = [validator]
        for v in vs:
            if isinstance(v, attr.validators._InValidator):
                if isinstance(v.options, string_types):
                    in_collections.append(list(all_substrings(v.options)))
                else:
                    in_collections.append(v.options)
            elif isinstance(v, attr.validators._InstanceOfValidator):
                validator_types.add(v.type)

    # This is the important line.  We compose the final strategy from various
    # parts.  The default value, if any, is the minimal shrink, followed by
    # None (again, if allowed).  We then prefer to sample from values passed
    # to an in_ validator if available, but infer from a type otherwise.
    # Pick one because (sampled_from((1, 2)) | from_type(int)) would usually
    # fail validation by generating e.g. zero!
    if in_collections:
        sample = st.sampled_from(list(ordered_intersection(in_collections)))
        strat = default | null | sample
    else:
        strat = default | null | types_to_strategy(attrib, validator_types)

    # Better to give a meaningful error here than an opaque "could not draw"
    # when we try to get a value but have lost track of where this was created.
    if strat.is_empty:
        raise ResolutionFailed(
            "Cannot infer a strategy from the default, validator, type, or "
            "converter for attribute=%r of class=%r" % (attrib, target)
        )
    return strat
예제 #2
0
def _get_strategy_for_field(f):
    if f.choices:
        choices = []
        for value, name_or_optgroup in f.choices:
            if isinstance(name_or_optgroup, (list, tuple)):
                choices.extend(key for key, _ in name_or_optgroup)
            else:
                choices.append(value)
        if isinstance(f, (dm.CharField, dm.TextField)) and f.blank:
            choices.insert(0, u'')
        strategy = st.sampled_from(choices)
    elif type(f) == dm.SlugField:
        strategy = st.text(alphabet=string.ascii_letters + string.digits,
                           min_size=(None if f.blank else 1),
                           max_size=f.max_length)
    elif type(f) == dm.GenericIPAddressField:
        lookup = {'both': ip4_addr_strings() | ip6_addr_strings(),
                  'ipv4': ip4_addr_strings(), 'ipv6': ip6_addr_strings()}
        strategy = lookup[f.protocol.lower()]
    elif type(f) in (dm.TextField, dm.CharField):
        strategy = st.text(min_size=(None if f.blank else 1),
                           max_size=f.max_length)
    elif type(f) == dm.DecimalField:
        bound = Decimal(10 ** f.max_digits - 1) / (10 ** f.decimal_places)
        strategy = st.decimals(min_value=-bound, max_value=bound,
                               places=f.decimal_places)
    else:
        strategy = field_mappings().get(type(f), st.nothing())
    if f.validators:
        strategy = strategy.filter(validator_to_filter(f))
    if f.null:
        strategy = st.one_of(st.none(), strategy)
    return strategy
def test_cannot_register_empty():
    # Cannot register and did not register
    with pytest.raises(InvalidArgument):
        st.register_type_strategy(UnknownType, st.nothing())
    fails = st.from_type(UnknownType)
    with pytest.raises(ResolutionFailed):
        fails.example()
    assert UnknownType not in types._global_type_lookup
예제 #4
0
def fill_for(elements, unique, fill, name=''):
    if fill is None:
        if unique or not elements.has_reusable_values:
            fill = st.nothing()
        else:
            fill = elements
    else:
        st.check_strategy(fill, '%s.fill' % (name,) if name else 'fill')
    return fill
예제 #5
0
def _get_strategy_for_field(f):
    # type: (Type[dm.Field]) -> st.SearchStrategy[Any]
    if f.choices:
        choices = []  # type: list
        for value, name_or_optgroup in f.choices:
            if isinstance(name_or_optgroup, (list, tuple)):
                choices.extend(key for key, _ in name_or_optgroup)
            else:
                choices.append(value)
        if isinstance(f, (dm.CharField, dm.TextField)) and f.blank:
            choices.insert(0, u'')
        strategy = st.sampled_from(choices)
    elif type(f) == dm.SlugField:
        strategy = st.text(alphabet=string.ascii_letters + string.digits,
                           min_size=(0 if f.blank else 1),
                           max_size=f.max_length)
    elif type(f) == dm.GenericIPAddressField:
        lookup = {'both': ip4_addr_strings() | ip6_addr_strings(),
                  'ipv4': ip4_addr_strings(), 'ipv6': ip6_addr_strings()}
        strategy = lookup[f.protocol.lower()]
    elif type(f) in (dm.TextField, dm.CharField):
        strategy = st.text(
            alphabet=st.characters(blacklist_characters=u'\x00',
                                   blacklist_categories=('Cs',)),
            min_size=(0 if f.blank else 1),
            max_size=f.max_length,
        )
        # We can infer a vastly more precise strategy by considering the
        # validators as well as the field type.  This is a minimal proof of
        # concept, but we intend to leverage the idea much more heavily soon.
        # See https://github.com/HypothesisWorks/hypothesis-python/issues/1116
        re_validators = [
            v for v in f.validators
            if isinstance(v, validators.RegexValidator) and not v.inverse_match
        ]
        if re_validators:
            regexes = [re.compile(v.regex, v.flags) if isinstance(v.regex, str)
                       else v.regex for v in re_validators]
            # This strategy generates according to one of the regexes, and
            # filters using the others.  It can therefore learn to generate
            # from the most restrictive and filter with permissive patterns.
            # Not maximally efficient, but it makes pathological cases rarer.
            # If you want a challenge: extend https://qntm.org/greenery to
            # compute intersections of the full Python regex language.
            strategy = st.one_of(*[st.from_regex(r) for r in regexes])
    elif type(f) == dm.DecimalField:
        bound = Decimal(10 ** f.max_digits - 1) / (10 ** f.decimal_places)
        strategy = st.decimals(min_value=-bound, max_value=bound,
                               places=f.decimal_places)
    else:
        strategy = field_mappings().get(type(f), st.nothing())
    if f.validators:
        strategy = strategy.filter(validator_to_filter(f))
    if f.null:
        strategy = st.one_of(st.none(), strategy)
    return strategy
def test_errors_if_generic_resolves_empty():
    try:
        st.register_type_strategy(UnknownType, lambda _: st.nothing())
        fails_1 = st.from_type(UnknownType)
        with pytest.raises(ResolutionFailed):
            fails_1.example()
        fails_2 = st.from_type(ParentUnknownType)
        with pytest.raises(ResolutionFailed):
            fails_2.example()
    finally:
        types._global_type_lookup.pop(UnknownType)
        st.from_type.__clear_cache()
예제 #7
0
def column_strategy(draw):
    name = draw(st.none() | st.text())
    dtype = draw(npst.scalar_dtypes().filter(supported_by_pandas))
    pass_dtype = not draw(st.booleans())
    if pass_dtype:
        pass_elements = not draw(st.booleans())
    else:
        pass_elements = True
    if pass_elements:
        elements = npst.from_dtype(dtype)
    else:
        elements = None

    unique = draw(st.booleans())
    fill = st.nothing() if draw(st.booleans()) else None

    return pdst.column(
        name=name, dtype=dtype, unique=unique, fill=fill, elements=elements)
예제 #8
0
def types_to_strategy(attrib, types):
    """Find all the type metadata for this attribute, reconcile it, and infer a
    strategy from the mess."""
    # If we know types from the validator(s), that's sufficient.
    if len(types) == 1:
        typ, = types
        if isinstance(typ, tuple):
            return st.one_of(*map(st.from_type, typ))
        return st.from_type(typ)
    elif types:
        # We have a list of tuples of types, and want to find a type
        # (or tuple of types) that is a subclass of all of of them.
        type_tuples = [k if isinstance(k, tuple) else (k,) for k in types]
        # Flatten the list, filter types that would fail validation, and
        # sort so that ordering is stable between runs and shrinks well.
        allowed = [
            t
            for t in set(sum(type_tuples, ()))
            if all(issubclass(t, tup) for tup in type_tuples)
        ]
        allowed.sort(key=type_sorting_key)
        return st.one_of([st.from_type(t) for t in allowed])

    # Otherwise, try the `type` attribute as a fallback, and finally try
    # the type hints on a converter (desperate!) before giving up.
    if isinstance(getattr(attrib, "type", None), type):
        # The convoluted test is because variable annotations may be stored
        # in string form; attrs doesn't evaluate them and we don't handle them.
        # See PEP 526, PEP 563, and Hypothesis issue #1004 for details.
        return st.from_type(attrib.type)

    converter = getattr(attrib, "converter", None)
    if isinstance(converter, type):
        return st.from_type(converter)
    elif callable(converter):
        hints = get_type_hints(converter)
        if "return" in hints:
            return st.from_type(hints["return"])

    return st.nothing()
def test_can_minimize_based_on_two_columns_independently(
        disable_fill, non_standard_index):
    columns = [
        pdst.column(
            name,
            dtype=bool,
            fill=st.nothing() if name in disable_fill else None,
        ) for name in ['A', 'B', 'C']
    ]

    x = minimal(
        pdst.data_frames(
            columns,
            index=pdst.indexes(dtype=int) if non_standard_index else None,
        ),
        lambda x: x['A'].any() and x['B'].any() and x['C'].any(),
        random=Random(0),
    )
    assert len(x['A']) == 1
    assert x['A'][0] == 1
    assert x['B'][0] == 1
    assert x['C'][0] == 1
def string_schema(schema: dict) -> st.SearchStrategy[str]:
    """Handle schemata for strings."""
    # also https://json-schema.org/latest/json-schema-validation.html#rfc.section.7
    min_size = schema.get("minLength", 0)
    max_size = schema.get("maxLength", float("inf"))
    strategy = st.text(min_size=min_size, max_size=schema.get("maxLength"))
    if schema.get("format") in STRING_FORMATS:
        # Unknown "format" specifiers should be ignored for validation.
        # See https://json-schema.org/latest/json-schema-validation.html#format
        strategy = STRING_FORMATS[schema["format"]]
        if "pattern" in schema:
            # This isn't really supported, but we'll do our best.
            strategy = strategy.filter(
                lambda s: re.search(schema["pattern"], string=s) is not None)
    elif "pattern" in schema:
        try:
            re.compile(schema["pattern"])
            strategy = st.from_regex(schema["pattern"])
        except re.error:
            # Patterns that are invalid in Python, or just malformed
            return st.nothing()
    return strategy.filter(lambda s: min_size <= len(s) <= max_size)
예제 #11
0
파일: attrs.py 프로젝트: orivej/hypothesis
def types_to_strategy(attrib, types):
    """Find all the type metadata for this attribute, reconcile it, and infer a
    strategy from the mess."""
    # If we know types from the validator(s), that's sufficient.
    if len(types) == 1:
        (typ, ) = types
        if isinstance(typ, tuple):
            return st.one_of(*map(st.from_type, typ))
        return st.from_type(typ)
    elif types:
        # We have a list of tuples of types, and want to find a type
        # (or tuple of types) that is a subclass of all of of them.
        type_tuples = [k if isinstance(k, tuple) else (k, ) for k in types]
        # Flatten the list, filter types that would fail validation, and
        # sort so that ordering is stable between runs and shrinks well.
        allowed = [
            t for t in set(sum(type_tuples, ())) if all(
                issubclass(t, tup) for tup in type_tuples)
        ]
        allowed.sort(key=type_sorting_key)
        return st.one_of([st.from_type(t) for t in allowed])

    # Otherwise, try the `type` attribute as a fallback, and finally try
    # the type hints on a converter (desperate!) before giving up.
    if is_a_type(getattr(attrib, "type", None)):
        # The convoluted test is because variable annotations may be stored
        # in string form; attrs doesn't evaluate them and we don't handle them.
        # See PEP 526, PEP 563, and Hypothesis issue #1004 for details.
        return st.from_type(attrib.type)

    converter = getattr(attrib, "converter", None)
    if isinstance(converter, type):
        return st.from_type(converter)
    elif callable(converter):
        hints = get_type_hints(converter)
        if "return" in hints:
            return st.from_type(hints["return"])

    return st.nothing()
예제 #12
0
def _strategy_for(param: inspect.Parameter) -> Union[st.SearchStrategy, InferType]:
    # If our default value is an Enum or a boolean, we assume that any value
    # of that type is acceptable.  Otherwise, we only generate the default.
    if isinstance(param.default, bool):
        return st.booleans()
    if isinstance(param.default, enum.Enum):
        return st.sampled_from(type(param.default))
    if param.default is not inspect.Parameter.empty:
        # Using `st.from_type(type(param.default))` would  introduce spurious
        # failures in cases like the `flags` argument to regex functions.
        # Better in to keep it simple, and let the user elaborate if desired.
        return st.just(param.default)
    # If there's no annotation and no default value, we check against a table
    # of guesses of simple strategies for common argument names.
    if "string" in param.name and "as" not in param.name:
        return st.text()
    for strategy, names in _GUESS_STRATEGIES_BY_NAME:
        if param.name in names:
            return strategy
    # And if all that failed, we'll return nothing() - the user will have to
    # fill this in by hand, and we'll leave a comment to that effect later.
    return st.nothing()
예제 #13
0
def test_can_minimize_based_on_two_columns_independently(
    disable_fill, non_standard_index
):
    columns = [
        pdst.column(
            name, dtype=bool,
            fill=st.nothing() if name in disable_fill else None,
        )
        for name in ['A', 'B', 'C']
    ]

    x = minimal(
        pdst.data_frames(
            columns,
            index=pdst.indexes(dtype=int) if non_standard_index else None,
        ),
        lambda x: x['A'].any() and x['B'].any() and x['C'].any(),
        random=Random(0),
    )
    assert len(x['A']) == 1
    assert x['A'][0] == 1
    assert x['B'][0] == 1
    assert x['C'][0] == 1
예제 #14
0
    def non_matching_string(self, draw, state):
        if not any(isinstance(x, tuple) for x in self.elements):
            # easy case, only chars
            return draw(st.characters(blacklist_characters=self.elements))

        # Now, we *could* iterate through to get the set of all allowed characters,
        # but that would be pretty slow.  Instead, we just get the highest and lowest
        # allowed codepoints and stay outside that interval, blacklisting individual
        # characters.  If we allow both chr(0) and chr(maxunicode), just give up.
        chars = "".join(x for x in self.elements if not isinstance(x, tuple))
        low = min(ord(x[0]) for x in self.elements if isinstance(x, tuple))
        high = max(ord(x[1]) for x in self.elements if isinstance(x, tuple))
        strat = st.nothing()
        if low > 0:
            strat |= st.characters(max_codepoint=low - 1,
                                   blacklist_characters=chars)
        if high < sys.maxunicode:
            strat |= st.characters(min_codepoint=high + 1,
                                   blacklist_characters=chars)
        try:
            return draw(strat)
        except InvalidArgument:
            reject()
예제 #15
0
def methods(draw,
		min_argc=None, # int
		max_argc=None, # int
		manual_argument_bindings=None, # {}
		manual_keyword_bindings=None, # {}
		body=_phony_callable,
		decorators=None, # [] itterable
		kwarginit=hs.nothing(),
		parent=classes()
	):
	"""DOCUMENT ME!!!"""
	check_strategy(parent, name="parent")
	check_type(dict, manual_argument_bindings, name="manual_argument_bindings")

	min_argc = 0 if min_argc is None \
		else check_valid_integer(min_argc, name="min_argc")
	max_argc = 0 if max_argc is None \
		else check_valid_integer(max_argc, name="max_argc")

	arguments = {0: "self"}
	arguments.update(manual_argument_bindings)

	container = draw(parent)
	method_body = draw(functions(
		binding_regex=binding_regex,
		min_argc=(min_argc + 1), max_argc=(max_argc+1),
		manual_argument_bindings = arguments,
		manual_keyword_bindings = manual_keyword_bindings, body=body,
		decorators = decorators, kwarginit = kwarginit
	))
	setattr(container, method_body.__name__, method_body)

	call = "".join(["container.", method_body.__name__, "(*args, **kwargs)"])
	def method_wrapper(*args, **kwargs):
		exec(call , locals())

	return method_wrapper
예제 #16
0
def _get_strategy_for_field(f):
    if f.choices:
        choices = []
        for value, name_or_optgroup in f.choices:
            if isinstance(name_or_optgroup, (list, tuple)):
                choices.extend(key for key, _ in name_or_optgroup)
            else:
                choices.append(value)
        if isinstance(f, (dm.CharField, dm.TextField)) and f.blank:
            choices.insert(0, u'')
        strategy = st.sampled_from(choices)
    elif type(f) == dm.SlugField:
        strategy = st.text(alphabet=string.ascii_letters + string.digits,
                           min_size=(None if f.blank else 1),
                           max_size=f.max_length)
    elif type(f) == dm.GenericIPAddressField:
        lookup = {
            'both': ip4_addr_strings() | ip6_addr_strings(),
            'ipv4': ip4_addr_strings(),
            'ipv6': ip6_addr_strings()
        }
        strategy = lookup[f.protocol.lower()]
    elif type(f) in (dm.TextField, dm.CharField):
        strategy = st.text(min_size=(None if f.blank else 1),
                           max_size=f.max_length)
    elif type(f) == dm.DecimalField:
        bound = Decimal(10**f.max_digits - 1) / (10**f.decimal_places)
        strategy = st.decimals(min_value=-bound,
                               max_value=bound,
                               places=f.decimal_places)
    else:
        strategy = field_mappings().get(type(f), st.nothing())
    if f.validators:
        strategy = strategy.filter(validator_to_filter(f))
    if f.null:
        strategy = st.one_of(st.none(), strategy)
    return strategy
예제 #17
0
def test_no_examples():
    assert_no_examples(st.nothing())
def test_empty_elements_with_max_size_is_deprecated():
    ds.lists(ds.nothing(), max_size=1).example()
예제 #19
0
from hypothesis import strategies as st
from hypothesis import find, given
from hypothesis.errors import InvalidArgument
from tests.common.debug import assert_no_examples


def test_resampling():
    x = find(
        st.lists(st.integers()).flatmap(
            lambda x: st.lists(st.sampled_from(x))),
        lambda x: len(x) >= 10 and len(set(x)) == 1)
    assert x == [0] * 10


@given(st.lists(st.nothing()))
def test_list_of_nothing(xs):
    assert xs == []


@given(st.sets(st.nothing()))
def test_set_of_nothing(xs):
    assert xs == set()


def test_validates_min_size():
    with pytest.raises(InvalidArgument):
        st.lists(st.nothing(), min_size=1).validate()


def test_function_composition():
예제 #20
0
def test_tuples_detect_empty_elements():
    assert st.tuples(st.nothing()).is_empty
예제 #21
0
def test_raises_on_no_examples():
    with pytest.raises(NoExamples):
        st.nothing().example()
예제 #22
0
import pytest

from hypothesis import strategies as st
from hypothesis import find, given
from hypothesis.errors import NoExamples, InvalidArgument


def test_resampling():
    x = find(
        st.lists(st.integers()).flatmap(
            lambda x: st.lists(st.sampled_from(x))),
        lambda x: len(x) >= 10 and len(set(x)) == 1)
    assert x == [0] * 10


@given(st.lists(st.nothing()))
def test_list_of_nothing(xs):
    assert xs == []


@given(st.sets(st.nothing()))
def test_set_of_nothing(xs):
    assert xs == set()


def test_validates_min_size():
    with pytest.raises(InvalidArgument):
        st.lists(st.nothing(), min_size=1).validate()


def test_one_of_is_or_identity():
def test_empty_strategy_is_invalid():
    d = ConjectureData.for_buffer(hbytes(0))
    with pytest.raises(StopTest):
        d.draw(st.nothing())
    assert d.status == Status.INVALID
예제 #24
0
def test_raises_on_no_examples():
    with pytest.raises(Unsatisfiable):
        st.nothing().example()
예제 #25
0
def test_fixed_dictionaries_detect_empty_values():
    assert st.fixed_dictionaries({'a': st.nothing()}).is_empty
예제 #26
0
def test_no_examples():
    assert_no_examples(st.nothing())
예제 #27
0
def test_tuples_detect_empty_elements():
    assert st.tuples(st.nothing()).is_empty
예제 #28
0
def test_function_composition():
    assert st.nothing().map(lambda x: 'hi').is_empty
    assert st.nothing().filter(lambda x: True).is_empty
    assert st.nothing().flatmap(lambda x: st.integers()).is_empty
예제 #29
0
def test_validates_min_size():
    with pytest.raises(InvalidArgument):
        st.lists(st.nothing(), min_size=1).validate()
예제 #30
0
def test_overflowing_floats_are_deprecated(fill, data):
    kw = dict(elements=st.floats(min_value=65520, allow_infinity=False))
    if fill:
        kw = dict(elements=st.nothing(), fill=kw['elements'])
    arr = data.draw(nps.arrays(dtype='float16', shape=(1,), **kw))
    assert np.isinf(arr[0])
 (ds.floats, {"exclude_min": None}),
 (ds.floats, {"exclude_max": None}),
 (ds.floats, {"exclude_min": True}),  # because min_value=None
 (ds.floats, {"exclude_max": True}),  # because max_value=None
 (ds.fractions, {"min_value": 2, "max_value": 1}),
 (ds.fractions, {"min_value": float("nan")}),
 (ds.fractions, {"max_value": float("nan")}),
 (ds.fractions, {"max_denominator": 0}),
 (ds.fractions, {"max_denominator": 1.5}),
 (ds.fractions, {"min_value": complex(1, 2)}),
 (ds.lists, {"elements": ds.integers(), "min_size": 10, "max_size": 9}),
 (ds.lists, {"elements": ds.integers(), "min_size": -10, "max_size": -9}),
 (ds.lists, {"elements": ds.integers(), "max_size": -9}),
 (ds.lists, {"elements": ds.integers(), "min_size": -10}),
 (ds.lists, {"elements": ds.integers(), "min_size": float("nan")}),
 (ds.lists, {"elements": ds.nothing(), "max_size": 1}),
 (ds.lists, {"elements": "hi"}),
 (ds.lists, {"elements": ds.integers(), "unique_by": 1}),
 (ds.lists, {"elements": ds.integers(), "unique_by": ()}),
 (ds.lists, {"elements": ds.integers(), "unique_by": (1,)}),
 (ds.text, {"min_size": 10, "max_size": 9}),
 (ds.text, {"alphabet": [1]}),
 (ds.text, {"alphabet": ["abc"]}),
 (ds.binary, {"min_size": 10, "max_size": 9}),
 (ds.floats, {"min_value": float("nan")}),
 (ds.floats, {"min_value": "0"}),
 (ds.floats, {"max_value": "0"}),
 (ds.floats, {"max_value": 0.0, "min_value": 1.0}),
 (ds.floats, {"min_value": 0.0, "allow_nan": True}),
 (ds.floats, {"max_value": 0.0, "allow_nan": True}),
 (ds.floats, {"min_value": 0.0, "max_value": 1.0, "allow_infinity": True}),
예제 #32
0

@pytest.mark.parametrize(
    ("col", "strat"),
    [
        ((), tuples()),
        ([], lists(none(), max_size=0)),
        (set(), sets(none(), max_size=0)),
        (frozenset(), frozensets(none(), max_size=0)),
        ({}, fixed_dictionaries({})),
        ({}, fixed_dictionaries({}, optional={})),
        (OrderedDict(), fixed_dictionaries(OrderedDict(), optional=OrderedDict())),
        ({}, fixed_dictionaries({}, optional={1: booleans()})),
        ({0: False}, fixed_dictionaries({0: booleans()}, optional={1: booleans()})),
        ({}, fixed_dictionaries({}, optional={(): booleans(), 0: booleans()})),
        ([], lists(nothing())),
        ([], lists(nothing(), unique=True)),
    ],
)
def test_find_empty_collection_gives_empty(col, strat):
    assert minimal(strat, lambda x: True) == col


@pytest.mark.parametrize(
    ("coltype", "strat"), [(list, lists), (set, sets), (frozenset, frozensets)]
)
def test_find_non_empty_collection_gives_single_zero(coltype, strat):
    assert minimal(strat(integers()), bool) == coltype((0,))


@pytest.mark.parametrize(
예제 #33
0
 (ds.floats, {"max_value": 1.8, "width": 32}),
 (ds.fractions, {"min_value": 2, "max_value": 1}),
 (ds.fractions, {"min_value": math.nan}),
 (ds.fractions, {"max_value": math.nan}),
 (ds.fractions, {"max_denominator": 0}),
 (ds.fractions, {"max_denominator": 1.5}),
 (ds.fractions, {"min_value": complex(1, 2)}),
 (ds.fractions, {"min_value": "1/3", "max_value": "1/2", "max_denominator": 2}),
 (ds.fractions, {"min_value": "0", "max_value": "1/3", "max_denominator": 2}),
 (ds.fractions, {"min_value": "1/3", "max_value": "1/3", "max_denominator": 2}),
 (ds.lists, {"elements": ds.integers(), "min_size": 10, "max_size": 9}),
 (ds.lists, {"elements": ds.integers(), "min_size": -10, "max_size": -9}),
 (ds.lists, {"elements": ds.integers(), "max_size": -9}),
 (ds.lists, {"elements": ds.integers(), "min_size": -10}),
 (ds.lists, {"elements": ds.integers(), "min_size": math.nan}),
 (ds.lists, {"elements": ds.nothing(), "max_size": 1}),
 (ds.lists, {"elements": "hi"}),
 (ds.lists, {"elements": ds.integers(), "unique_by": 1}),
 (ds.lists, {"elements": ds.integers(), "unique_by": ()}),
 (ds.lists, {"elements": ds.integers(), "unique_by": (1,)}),
 (ds.lists, {"elements": ds.sampled_from([0, 1]), "min_size": 3, "unique": True}),
 (ds.text, {"min_size": 10, "max_size": 9}),
 (ds.text, {"alphabet": [1]}),
 (ds.text, {"alphabet": ["abc"]}),
 (ds.binary, {"min_size": 10, "max_size": 9}),
 (ds.floats, {"min_value": math.nan}),
 (ds.floats, {"min_value": "0"}),
 (ds.floats, {"max_value": "0"}),
 (ds.floats, {"min_value": 0.0, "max_value": -0.0}),
 (ds.floats, {"min_value": 0.0, "max_value": 1.0, "allow_infinity": True}),
 (ds.floats, {"max_value": 0.0, "min_value": 1.0}),
예제 #34
0
파일: types.py 프로젝트: sunito/hypothesis
        return st.frozensets(st.from_type(thing.__args__[0]))

    @register(typing.Dict, st.builds(dict))
    def resolve_Dict(thing):
        # If thing is a Collection instance, we need to fill in the values
        keys_vals = [st.from_type(t) for t in thing.__args__] * 2
        return st.dictionaries(keys_vals[0], keys_vals[1])

    @register('DefaultDict', st.builds(collections.defaultdict))
    def resolve_DefaultDict(thing):
        return resolve_Dict(thing).map(
            lambda d: collections.defaultdict(None, d))

    @register(typing.ItemsView, st.builds(dict).map(dict.items))
    def resolve_ItemsView(thing):
        return resolve_Dict(thing).map(dict.items)

    @register(typing.KeysView, st.builds(dict).map(dict.keys))
    def resolve_KeysView(thing):
        return st.dictionaries(st.from_type(thing.__args__[0]), st.none()
                               ).map(dict.keys)

    @register(typing.ValuesView, st.builds(dict).map(dict.values))
    def resolve_ValuesView(thing):
        return st.dictionaries(st.integers(), st.from_type(thing.__args__[0])
                               ).map(dict.values)

    @register(typing.Iterator, st.iterables(st.nothing()))
    def resolve_Iterator(thing):
        return st.iterables(st.from_type(thing.__args__[0]))
     "max_size": -9
 }),
 (ds.lists, {
     "elements": ds.integers(),
     "max_size": -9
 }),
 (ds.lists, {
     "elements": ds.integers(),
     "min_size": -10
 }),
 (ds.lists, {
     "elements": ds.integers(),
     "min_size": math.nan
 }),
 (ds.lists, {
     "elements": ds.nothing(),
     "max_size": 1
 }),
 (ds.lists, {
     "elements": "hi"
 }),
 (ds.lists, {
     "elements": ds.integers(),
     "unique_by": 1
 }),
 (ds.lists, {
     "elements": ds.integers(),
     "unique_by": ()
 }),
 (ds.lists, {
     "elements": ds.integers(),
예제 #36
0
def test_one_of_is_or_identity():
    x = st.integers()
    assert (x | st.nothing()) is x
    assert (st.nothing() | x) is x
예제 #37
0
def test_validates_min_size():
    with pytest.raises(InvalidArgument):
        st.lists(st.nothing(), min_size=1).validate()
예제 #38
0
import hypothesis.strategies as st
from tests.common.arguments import argument_validation_test, e

BAD_ARGS = []


def adjust(ex, **kwargs):
    f, a, b = ex
    b = dict(b)
    b.update(kwargs)
    BAD_ARGS.append((f, a, b))


for ex in [
    e(st.lists, st.integers()),
    e(st.sets, st.integers()),
    e(st.frozensets, st.integers()),
    e(st.dictionaries, st.integers(), st.integers()),
    e(st.text),
    e(st.binary),
]:
    adjust(ex, min_size=-1)
    adjust(ex, max_size=-1)
    adjust(ex, min_size="no")
    adjust(ex, max_size="no")


BAD_ARGS.extend([e(st.lists, st.nothing(), unique=True, min_size=1)])

test_raise_invalid_argument = argument_validation_test(BAD_ARGS)
예제 #39
0
def test_one_of_empty():
    assert st.one_of() is st.nothing()
예제 #40
0
from hypothesis import given, strategies as st
from hypothesis.errors import InvalidArgument
from tests.common.debug import assert_no_examples, minimal


def test_resampling():
    x = minimal(
        st.lists(st.integers(),
                 min_size=1).flatmap(lambda x: st.lists(st.sampled_from(x))),
        lambda x: len(x) >= 10 and len(set(x)) == 1,
    )
    assert x == [0] * 10


@given(st.lists(st.nothing()))
def test_list_of_nothing(xs):
    assert xs == []


@given(st.sets(st.nothing()))
def test_set_of_nothing(xs):
    assert xs == set()


def test_validates_min_size():
    with pytest.raises(InvalidArgument):
        st.lists(st.nothing(), min_size=1).validate()


def test_function_composition():
예제 #41
0
from hypothesis import given, infer
from hypothesis.errors import InvalidArgument, ResolutionFailed
from hypothesis.searchstrategy import types
from hypothesis.internal.compat import PY2, integer_types

# Build a set of all types output by core strategies
blacklist = [
    'builds', 'iterables', 'permutations', 'random_module', 'randoms',
    'runner', 'sampled_from', 'streaming', 'choices',
]
types_with_core_strat = set(integer_types)
for thing in (getattr(st, name) for name in sorted(st._strategies)
              if name in dir(st) and name not in blacklist):
    for n in range(3):
        try:
            ex = thing(*([st.nothing()] * n)).example()
            types_with_core_strat.add(type(ex))
            break
        except (TypeError, InvalidArgument):
            continue


@pytest.mark.parametrize('typ', sorted(types_with_core_strat, key=str))
def test_resolve_core_strategies(typ):
    @given(st.from_type(typ))
    def inner(ex):
        if PY2 and issubclass(typ, integer_types):
            assert isinstance(ex, integer_types)
        else:
            assert isinstance(ex, typ)
예제 #42
0
def test_empty_strategy_is_invalid():
    d = ConjectureData.for_buffer(bytes(0))
    with pytest.raises(StopTest):
        d.draw(st.nothing())
    assert d.status == Status.INVALID
    text,
    tuples,
)
from tests.common.debug import find_any, minimal
from tests.common.utils import flaky


@pytest.mark.parametrize(
    (u"col", u"strat"),
    [
        ((), tuples()),
        ([], lists(none(), max_size=0)),
        (set(), sets(none(), max_size=0)),
        (frozenset(), frozensets(none(), max_size=0)),
        ({}, fixed_dictionaries({})),
        ([], lists(nothing())),
        ([], lists(nothing(), unique=True)),
    ],
)
def test_find_empty_collection_gives_empty(col, strat):
    assert minimal(strat, lambda x: True) == col


@pytest.mark.parametrize(
    (u"coltype", u"strat"), [(list, lists), (set, sets), (frozenset, frozensets)]
)
def test_find_non_empty_collection_gives_single_zero(coltype, strat):
    assert minimal(strat(integers()), bool) == coltype((0,))


@pytest.mark.parametrize(
예제 #44
0
from hypothesis import strategies as st
from hypothesis import find, given
from hypothesis.errors import InvalidArgument
from tests.common.debug import assert_no_examples


def test_resampling():
    x = find(
        st.lists(
            st.integers()).flatmap(lambda x: st.lists(st.sampled_from(x))),
        lambda x: len(x) >= 10 and len(set(x)) == 1)
    assert x == [0] * 10


@given(st.lists(st.nothing()))
def test_list_of_nothing(xs):
    assert xs == []


@given(st.sets(st.nothing()))
def test_set_of_nothing(xs):
    assert xs == set()


def test_validates_min_size():
    with pytest.raises(InvalidArgument):
        st.lists(st.nothing(), min_size=1).validate()


def test_function_composition():
예제 #45
0

@given(
    nps.arrays(
        dtype="float16",
        shape=10,
        unique=True,
        elements=st.integers(1, 9),
        fill=st.just(np.nan),
    )
)
def test_unique_array_with_fill_can_use_all_elements(arr):
    assume(len(set(arr)) == arr.size)


@given(nps.arrays(dtype="uint8", shape=25, unique=True, fill=st.nothing()))
def test_unique_array_without_fill(arr):
    # This test covers the collision-related branches for fully dense unique arrays.
    # Choosing 25 of 256 possible elements means we're almost certain to see colisions
    # thanks to the 'birthday paradox', but finding unique elemennts is still easy.
    assume(len(set(arr)) == arr.size)


@given(ndim=st.integers(0, 5), data=st.data())
def test_mapped_positive_axes_are_unique(ndim, data):
    min_size = data.draw(st.integers(0, ndim), label="min_size")
    max_size = data.draw(st.integers(min_size, ndim), label="max_size")
    axes = data.draw(
        nps.valid_tuple_axes(ndim, min_size=min_size, max_size=max_size), label="axes"
    )
    assert len(set(axes)) == len({i if 0 < i else ndim + i for i in axes})
예제 #46
0
def test_function_composition():
    assert st.nothing().map(lambda x: 'hi').is_empty
    assert st.nothing().filter(lambda x: True).is_empty
    assert st.nothing().flatmap(lambda x: st.integers()).is_empty
예제 #47
0
    def resolve_ItemsView(thing):
        return resolve_Dict(thing).map(dict.items)

    @register(typing.KeysView, st.builds(dict).map(dict.keys))
    def resolve_KeysView(thing):
        return st.dictionaries(st.from_type(thing.__args__[0]), st.none()).map(
            dict.keys
        )

    @register(typing.ValuesView, st.builds(dict).map(dict.values))
    def resolve_ValuesView(thing):
        return st.dictionaries(st.integers(), st.from_type(thing.__args__[0])).map(
            dict.values
        )

    @register(typing.Iterator, st.iterables(st.nothing()))
    def resolve_Iterator(thing):
        return st.iterables(st.from_type(thing.__args__[0]))

    @register(typing.Callable, st.functions())
    def resolve_Callable(thing):
        # Generated functions either accept no arguments, or arbitrary arguments.
        # This is looser than ideal, but anything tighter would generally break
        # use of keyword arguments and we'd rather not force positional-only.
        if not thing.__args__:  # pragma: no cover  # varies by minor version
            return st.functions()
        return st.functions(
            like=(lambda: None) if len(thing.__args__) == 1 else (lambda *a, **k: None),
            returns=st.from_type(thing.__args__[-1]),
        )
예제 #48
0
def test_fixed_dictionaries_detect_empty_values():
    assert st.fixed_dictionaries({'a': st.nothing()}).is_empty
    f, a, b = ex
    b = dict(b)
    b.update(kwargs)
    BAD_ARGS.append((f, a, b))


for ex in [
    e(st.lists, st.integers()),
    e(st.sets, st.integers()),
    e(st.frozensets, st.integers()),
    e(st.dictionaries, st.integers(), st.integers()),
    e(st.text),
    e(st.binary)
]:
    adjust(ex, average_size=10, max_size=9),
    adjust(ex, average_size=10, min_size=11),

    adjust(ex, min_size=-1)
    adjust(ex, average_size=-1)
    adjust(ex, max_size=-1)
    adjust(ex, min_size='no')
    adjust(ex, average_size='no')
    adjust(ex, max_size='no')


BAD_ARGS.extend([
    e(st.lists, st.nothing(), unique=True, min_size=1),
])

test_raise_invalid_argument = argument_validation_test(BAD_ARGS)
     'max_value': 1.0, 'min_value': -1.0, 'allow_infinity': False}),
 (ds.decimals, {'min_value': 1.0, 'allow_nan': False}),
 (ds.decimals, {'max_value': 1.0, 'allow_nan': False}),
 (ds.decimals, {'max_value': 1.0, 'min_value': -1.0, 'allow_nan': False}),
 (ds.decimals, {'min_value': '-inf'}),
 (ds.decimals, {'max_value': 'inf'}),
 (ds.fractions, {
     'min_value': -1, 'max_value': 1, 'max_denominator': 1000}),
 (ds.fractions, {'min_value': 1, 'max_value': 1}),
 (ds.fractions, {'min_value': 1, 'max_value': 1, 'max_denominator': 2}),
 (ds.fractions, {'min_value': 1.0}),
 (ds.fractions, {'min_value': decimal.Decimal('1.0')}),
 (ds.fractions, {'min_value': fractions.Fraction(1, 2)}),
 (ds.fractions, {'min_value': '1/2', 'max_denominator': 1}),
 (ds.fractions, {'max_value': '1/2', 'max_denominator': 1}),
 (ds.lists, {'elements': ds.nothing(), 'max_size': 0}),
 (ds.lists, {'elements': ds.integers()}),
 (ds.lists, {'elements': ds.integers(), 'max_size': 5}),
 (ds.lists, {'elements': ds.booleans(), 'min_size': 5}),
 (ds.lists, {'elements': ds.booleans(), 'min_size': 5, 'max_size': 10}),
 (ds.sets, {
     'min_size': 10, 'max_size': 10, 'elements': ds.integers(),
 }),
 (ds.booleans, {}),
 (ds.just, {'value': 'hi'}),
 (ds.integers, {'min_value': 12, 'max_value': 12}),
 (ds.floats, {}),
 (ds.floats, {'min_value': 1.0}),
 (ds.floats, {'max_value': 1.0}),
 (ds.floats, {'max_value': 1.0, 'min_value': -1.0}),
 (ds.floats, {
from hypothesis.errors import InvalidArgument, ResolutionFailed, \
    HypothesisDeprecationWarning
from hypothesis.searchstrategy import types
from hypothesis.internal.compat import PY2, integer_types

# Build a set of all types output by core strategies
blacklist = [
    'builds', 'iterables', 'permutations', 'random_module', 'randoms',
    'runner', 'sampled_from', 'streaming', 'choices',
]
types_with_core_strat = set(integer_types)
for thing in (getattr(st, name) for name in sorted(st._strategies)
              if name in dir(st) and name not in blacklist):
    for n in range(3):
        try:
            ex = thing(*([st.nothing()] * n)).example()
            types_with_core_strat.add(type(ex))
            break
        except (TypeError, InvalidArgument, HypothesisDeprecationWarning):
            continue


@pytest.mark.parametrize('typ', sorted(types_with_core_strat, key=str))
def test_resolve_core_strategies(typ):
    @given(st.from_type(typ))
    def inner(ex):
        if PY2 and issubclass(typ, integer_types):
            assert isinstance(ex, integer_types)
        else:
            assert isinstance(ex, typ)
예제 #52
0
def test_raises_on_no_examples():
    with pytest.raises(NoExamples):
        st.nothing().example()
예제 #53
0
def test_overflowing_integers_are_deprecated(fill, data):
    kw = dict(elements=st.just(300))
    if fill:
        kw = dict(elements=st.nothing(), fill=kw['elements'])
    arr = data.draw(nps.arrays(dtype='int8', shape=(1,), **kw))
    assert arr[0] == (300 % 256)
예제 #54
0
def test_overflowing_integers_are_deprecated(fill, data):
    kw = {"elements": st.just(300)}
    if fill:
        kw = {"elements": st.nothing(), "fill": kw["elements"]}
    arr = data.draw(nps.arrays(dtype="int8", shape=(1,), **kw))
    assert arr[0] == (300 % 256)
예제 #55
0
_update(top_coverage_callables, 'inspect',
        ['Signature.__init__', 'getinnerframes'])
_add(top_coverage_callables, 'logging', 'Handler.get_name')
_add(top_coverage_callables, 'os', 'times_result')
_add(top_coverage_callables, 'sqlite3', 'Connection.rollback')
_add(top_coverage_callables, 'symtable', 'Symbol.is_global')
_add(top_coverage_callables, 'tarfile', 'EOFHeaderError')
_add(top_coverage_callables, 'telnetlib', 'Telnet.fileno')
_add(top_coverage_callables, 'time', 'struct_time')
_update(top_coverage_callables, 'tkinter', ['Misc.focus_force', 'Wm.iconmask'])
_add(top_coverage_callables, 'turtle', 'RawTurtle.turtlesize')
_add(top_coverage_callables, 'weakref', 'ref')
_add(top_coverage_callables, 'zipfile', 'error')
top_coverage_callables = strategies.sampled_from(list(top_coverage_callables))
callables = (built_in_functions
             | classes
             | functions
             | methods
             | methods_descriptors
             | wrappers_descriptors)
partial_callables = callables.map(partial)
if platform.python_implementation() == 'PyPy':
    overloaded_callables = strategies.nothing()
else:
    overloaded_callables = strategies.sampled_from([int, reduce, super, type])
unsupported_callables = strategies.sampled_from(
    list(unsupported.built_in_functions
         | unsupported.classes
         | unsupported.methods_descriptors
         | unsupported.wrappers_descriptors))
예제 #56
0
def _arrays(
    xp: Any,
    dtype: Union[DataType, str, st.SearchStrategy[DataType],
                 st.SearchStrategy[str]],
    shape: Union[int, Shape, st.SearchStrategy[Shape]],
    *,
    elements: Optional[Union[Mapping[str, Any], st.SearchStrategy]] = None,
    fill: Optional[st.SearchStrategy[Any]] = None,
    unique: bool = False,
) -> st.SearchStrategy:
    """Returns a strategy for :xp-ref:`arrays <array_object.html>`.

    * ``dtype`` may be a :xp-ref:`valid dtype <data_types.html>` object or name,
      or a strategy that generates such values.
    * ``shape`` may be an integer >= 0, a tuple of such integers, or a strategy
      that generates such values.
    * ``elements`` is a strategy for values to put in the array. If ``None``
      then a suitable value will be inferred based on the dtype, which may give
      any legal value (including e.g. NaN for floats). If a mapping, it will be
      passed as ``**kwargs`` to :func:`from_dtype()` when inferring based on the dtype.
    * ``fill`` is a strategy that may be used to generate a single background
      value for the array. If ``None``, a suitable default will be inferred
      based on the other arguments. If set to
      :func:`~hypothesis.strategies.nothing` then filling behaviour will be
      disabled entirely and every element will be generated independently.
    * ``unique`` specifies if the elements of the array should all be distinct
      from one another; if fill is also set, the only valid values for fill to
      return are NaN values.

    Arrays of specified ``dtype`` and ``shape`` are generated for example
    like this:

    .. code-block:: pycon

      >>> from numpy import array_api as xp
      >>> xps.arrays(xp, xp.int8, (2, 3)).example()
      Array([[-8,  6,  3],
             [-6,  4,  6]], dtype=int8)

    Specifying element boundaries by a :obj:`python:dict` of the kwargs to pass
    to :func:`from_dtype` will ensure ``dtype`` bounds will be respected.

    .. code-block:: pycon

      >>> xps.arrays(xp, xp.int8, 3, elements={"min_value": 10}).example()
      Array([125, 13, 79], dtype=int8)

    Refer to :doc:`What you can generate and how <data>` for passing
    your own elements strategy.

    .. code-block:: pycon

      >>> xps.arrays(xp, xp.float32, 3, elements=floats(0, 1, width=32)).example()
      Array([ 0.88974794,  0.77387938,  0.1977879 ], dtype=float32)

    Array values are generated in two parts:

    1. A single value is drawn from the fill strategy and is used to create a
       filled array.
    2. Some subset of the coordinates of the array are populated with a value
       drawn from the elements strategy (or its inferred form).

    You can set ``fill`` to :func:`~hypothesis.strategies.nothing` if you want
    to disable this behaviour and draw a value for every element.

    By default ``arrays`` will attempt to infer the correct fill behaviour: if
    ``unique`` is also ``True``, no filling will occur. Otherwise, if it looks
    safe to reuse the values of elements across multiple coordinates (this will
    be the case for any inferred strategy, and for most of the builtins, but is
    not the case for mutable values or strategies built with flatmap, map,
    composite, etc.) then it will use the elements strategy as the fill, else it
    will default to having no fill.

    Having a fill helps Hypothesis craft high quality examples, but its
    main importance is when the array generated is large: Hypothesis is
    primarily designed around testing small examples. If you have arrays with
    hundreds or more elements, having a fill value is essential if you want
    your tests to run in reasonable time.
    """
    check_xp_attributes(xp, [
        "finfo", "asarray", "zeros", "full", "all", "isnan", "isfinite",
        "reshape"
    ])

    if isinstance(dtype, st.SearchStrategy):
        return dtype.flatmap(lambda d: _arrays(
            xp, d, shape, elements=elements, fill=fill, unique=unique))
    elif isinstance(dtype, str):
        dtype = dtype_from_name(xp, dtype)

    if isinstance(shape, st.SearchStrategy):
        return shape.flatmap(lambda s: _arrays(
            xp, dtype, s, elements=elements, fill=fill, unique=unique))
    elif isinstance(shape, int):
        shape = (shape, )
    elif not isinstance(shape, tuple):
        raise InvalidArgument(
            f"shape={shape} is not a valid shape or strategy")
    check_argument(
        all(isinstance(x, int) and x >= 0 for x in shape),
        f"shape={shape!r}, but all dimensions must be non-negative integers.",
    )

    if elements is None:
        elements = _from_dtype(xp, dtype)
    elif isinstance(elements, Mapping):
        elements = _from_dtype(xp, dtype, **elements)
    check_strategy(elements, "elements")

    if fill is None:
        assert isinstance(elements, st.SearchStrategy)  # for mypy
        if unique or not elements.has_reusable_values:
            fill = st.nothing()
        else:
            fill = elements
    check_strategy(fill, "fill")

    return ArrayStrategy(xp, elements, dtype, shape, fill, unique)
 (ds.fractions, {
     'min_value': decimal.Decimal('1.0')
 }),
 (ds.fractions, {
     'min_value': fractions.Fraction(1, 2)
 }),
 (ds.fractions, {
     'min_value': '1/2',
     'max_denominator': 2
 }),
 (ds.fractions, {
     'max_value': '1/2',
     'max_denominator': 3
 }),
 (ds.lists, {
     'elements': ds.nothing(),
     'max_size': 0
 }),
 (ds.lists, {
     'elements': ds.integers()
 }),
 (ds.lists, {
     'elements': ds.integers(),
     'max_size': 5
 }),
 (ds.lists, {
     'elements': ds.booleans(),
     'min_size': 5
 }),
 (ds.lists, {
     'elements': ds.booleans(),