Exemple #1
0
def from_model(
    model,  # type: Type[dm.Model]
    **field_strategies  # type: Union[st.SearchStrategy[Any], InferType]
):
    # type: (...) -> st.SearchStrategy[Any]
    """Return a strategy for examples of ``model``.

    .. warning::
        Hypothesis creates saved models. This will run inside your testing
        transaction when using the test runner, but if you use the dev console
        this will leave debris in your database.

    ``model`` must be an subclass of :class:`~django:django.db.models.Model`.
    Strategies for fields may be passed as keyword arguments, for example
    ``is_staff=st.just(False)``.

    Hypothesis can often infer a strategy based the field type and validators,
    and will attempt to do so for any required fields.  No strategy will be
    inferred for an :class:`~django:django.db.models.AutoField`, nullable field,
    foreign key, or field for which a keyword
    argument is passed to ``from_model()``.  For example,
    a Shop type with a foreign key to Company could be generated with::

        shop_strategy = from_model(Shop, company=from_model(Company))

    Like for :func:`~hypothesis.strategies.builds`, you can pass
    :obj:`~hypothesis.infer` as a keyword argument to infer a strategy for
    a field which has a default value instead of using the default.
    """
    if not issubclass(model, dm.Model):
        raise InvalidArgument("model=%r must be a subtype of Model" %
                              (model, ))

    fields_by_name = {f.name: f for f in model._meta.concrete_fields}
    for name, value in sorted(field_strategies.items()):
        if value is infer:
            field_strategies[name] = from_field(fields_by_name[name])
    for name, field in sorted(fields_by_name.items()):
        if (name not in field_strategies and not field.auto_created
                and field.default is dm.fields.NOT_PROVIDED):
            field_strategies[name] = from_field(field)

    for field in field_strategies:
        if model._meta.get_field(field).primary_key:
            # The primary key is generated as part of the strategy. We
            # want to find any existing row with this primary key and
            # overwrite its contents.
            kwargs = {field: field_strategies.pop(field)}
            kwargs["defaults"] = st.fixed_dictionaries(
                field_strategies)  # type: ignore
            return _models_impl(
                st.builds(model.objects.update_or_create, **kwargs))

    # The primary key is not generated as part of the strategy, so we
    # just match against any row that has the same value for all
    # fields.
    return _models_impl(
        st.builds(model.objects.get_or_create, **field_strategies))
def from_model(
    model,  # type: Type[dm.Model]
    **field_strategies  # type: Union[st.SearchStrategy[Any], InferType]
):
    # type: (...) -> st.SearchStrategy[Any]
    """Return a strategy for examples of ``model``.

    .. warning::
        Hypothesis creates saved models. This will run inside your testing
        transaction when using the test runner, but if you use the dev console
        this will leave debris in your database.

    ``model`` must be an subclass of :class:`~django:django.db.models.Model`.
    Strategies for fields may be passed as keyword arguments, for example
    ``is_staff=st.just(False)``.

    Hypothesis can often infer a strategy based the field type and validators,
    and will attempt to do so for any required fields.  No strategy will be
    inferred for an :class:`~django:django.db.models.AutoField`, nullable field,
    foreign key, or field for which a keyword
    argument is passed to ``from_model()``.  For example,
    a Shop type with a foreign key to Company could be generated with::

        shop_strategy = from_model(Shop, company=from_model(Company))

    Like for :func:`~hypothesis.strategies.builds`, you can pass
    :obj:`~hypothesis.infer` as a keyword argument to infer a strategy for
    a field which has a default value instead of using the default.
    """
    if not issubclass(model, dm.Model):
        raise InvalidArgument("model=%r must be a subtype of Model" % (model,))

    fields_by_name = {f.name: f for f in model._meta.concrete_fields}
    for name, value in sorted(field_strategies.items()):
        if value is infer:
            field_strategies[name] = from_field(fields_by_name[name])
    for name, field in sorted(fields_by_name.items()):
        if (
            name not in field_strategies
            and not field.auto_created
            and field.default is dm.fields.NOT_PROVIDED
        ):
            field_strategies[name] = from_field(field)

    for field in field_strategies:
        if model._meta.get_field(field).primary_key:
            # The primary key is generated as part of the strategy. We
            # want to find any existing row with this primary key and
            # overwrite its contents.
            kwargs = {field: field_strategies.pop(field)}
            kwargs["defaults"] = st.fixed_dictionaries(field_strategies)  # type: ignore
            return _models_impl(st.builds(model.objects.update_or_create, **kwargs))

    # The primary key is not generated as part of the strategy, so we
    # just match against any row that has the same value for all
    # fields.
    return _models_impl(st.builds(model.objects.get_or_create, **field_strategies))
Exemple #3
0
def from_dtype(dtype):
    # type: (np.dtype) -> st.SearchStrategy[Any]
    """Creates a strategy which can generate any value of the given dtype."""
    check_type(np.dtype, dtype, "dtype")
    # Compound datatypes, eg 'f4,f4,f4'
    if dtype.names is not None:
        # mapping np.void.type over a strategy is nonsense, so return now.
        return st.tuples(*[from_dtype(dtype.fields[name][0]) for name in dtype.names])

    # Subarray datatypes, eg '(2, 3)i4'
    if dtype.subdtype is not None:
        subtype, shape = dtype.subdtype
        return arrays(subtype, shape)

    # Scalar datatypes
    if dtype.kind == u"b":
        result = st.booleans()  # type: SearchStrategy[Any]
    elif dtype.kind == u"f":
        if dtype.itemsize == 2:
            result = st.floats(width=16)
        elif dtype.itemsize == 4:
            result = st.floats(width=32)
        else:
            result = st.floats()
    elif dtype.kind == u"c":
        if dtype.itemsize == 8:
            float32 = st.floats(width=32)
            result = st.builds(complex, float32, float32)
        else:
            result = st.complex_numbers()
    elif dtype.kind in (u"S", u"a"):
        # Numpy strings are null-terminated; only allow round-trippable values.
        # `itemsize == 0` means 'fixed length determined at array creation'
        result = st.binary(max_size=dtype.itemsize or None).filter(
            lambda b: b[-1:] != b"\0"
        )
    elif dtype.kind == u"u":
        result = st.integers(min_value=0, max_value=2 ** (8 * dtype.itemsize) - 1)
    elif dtype.kind == u"i":
        overflow = 2 ** (8 * dtype.itemsize - 1)
        result = st.integers(min_value=-overflow, max_value=overflow - 1)
    elif dtype.kind == u"U":
        # Encoded in UTF-32 (four bytes/codepoint) and null-terminated
        result = st.text(max_size=(dtype.itemsize or 0) // 4 or None).filter(
            lambda b: b[-1:] != u"\0"
        )
    elif dtype.kind in (u"m", u"M"):
        if "[" in dtype.str:
            res = st.just(dtype.str.split("[")[-1][:-1])
        else:
            res = st.sampled_from(TIME_RESOLUTIONS)
        result = st.builds(dtype.type, st.integers(-(2 ** 63), 2 ** 63 - 1), res)
    else:
        raise InvalidArgument(u"No strategy inference for {}".format(dtype))
    return result.map(dtype.type)
Exemple #4
0
def ip4_addr_strings():
    """A strategy for IPv4 address strings.

    This consists of four strings representing integers [0..255],
    without zero-padding, joined by dots.
    """
    return st.builds("{}.{}.{}.{}".format, *(4 * [st.integers(0, 255)]))
Exemple #5
0
def domains():
    """A strategy for :rfc:`1035` fully qualified domain names."""
    atoms = st.text(
        string.ascii_letters + "0123456789-", min_size=1, max_size=63
    ).filter(lambda s: "-" not in s[0] + s[-1])
    return st.builds(
        lambda x, y: ".".join(x + [y]),
        st.lists(atoms, min_size=1),
        # TODO: be more devious about top-level domains
        st.sampled_from(["com", "net", "org", "biz", "info"]),
    ).filter(lambda url: len(url) <= 255)
Exemple #6
0
def urls():
    # type: () -> SearchStrategy[Text]
    """A strategy for :rfc:`3986`, generating http/https URLs."""
    def url_encode(s):
        return "".join(c if c in URL_SAFE_CHARACTERS else "%%%02X" % ord(c)
                       for c in s)

    schemes = st.sampled_from(["http", "https"])
    ports = st.integers(min_value=0, max_value=2**16 - 1).map(":{}".format)
    paths = st.lists(st.text(string.printable).map(url_encode)).map("/".join)

    return st.builds(u"{}://{}{}/{}".format, schemes, domains(),
                     st.just(u"") | ports, paths)
Exemple #7
0
def urls():
    """A strategy for :rfc:`3986`, generating http/https URLs."""

    def url_encode(s):
        safe_chars = set(string.ascii_letters + string.digits + "$-_.+!*'(),")
        return "".join(c if c in safe_chars else "%%%02X" % ord(c) for c in s)

    schemes = st.sampled_from(["http", "https"])
    ports = st.integers(min_value=0, max_value=2 ** 16 - 1).map(":{}".format)
    paths = st.lists(st.text(string.printable).map(url_encode)).map(
        lambda path: "/".join([""] + path)
    )

    return st.builds(
        "{}://{}{}{}".format, schemes, domains(), st.one_of(st.just(""), ports), paths
    )
Exemple #8
0
def models(
    model,  # type: Type[dm.Model]
    **field_strategies  # type: Union[st.SearchStrategy[Any], DefaultValueType]
):
    # type: (...) -> st.SearchStrategy[Any]
    """Return a strategy for examples of ``model``.

    .. warning::
        Hypothesis creates saved models. This will run inside your testing
        transaction when using the test runner, but if you use the dev console
        this will leave debris in your database.

    ``model`` must be an subclass of :class:`~django:django.db.models.Model`.
    Strategies for fields may be passed as keyword arguments, for example
    ``is_staff=st.just(False)``.

    Hypothesis can often infer a strategy based the field type and validators
    - for best results, make sure your validators are derived from Django's
    and therefore have the known types and attributes.
    Passing a keyword argument skips inference for that field; pass a strategy
    or pass ``hypothesis.extra.django.models.default_value`` to skip
    inference for that field.

    Foreign keys are not automatically derived. If they're nullable they will
    default to always being null, otherwise you always have to specify them.
    For example, examples of a Shop type with a foreign key to Company could
    be generated with::

      shop_strategy = models(Shop, company=models(Company))
    """
    note_deprecation(
        "`hypothesis.extra.django.models.models` is deprecated; use `hypothesis.extra.django."
        "from_model` instead.",
        since="2019-01-10",
    )
    result = {}
    for k, v in field_strategies.items():
        if not isinstance(v, DefaultValueType):
            result[k] = v
    missed = []  # type: List[Text]
    for f in model._meta.concrete_fields:
        if not (f.name in field_strategies or isinstance(f, dm.AutoField)):
            result[f.name] = from_field(f)
            if result[f.name].is_empty:
                missed.append(f.name)
    if missed:
        raise InvalidArgument(
            u"Missing arguments for mandatory field%s %s for model %s"
            % (u"s" if len(missed) > 1 else u"", u", ".join(missed), model.__name__)
        )

    for field in result:
        if model._meta.get_field(field).primary_key:
            # The primary key is generated as part of the strategy. We
            # want to find any existing row with this primary key and
            # overwrite its contents.
            kwargs = {field: result.pop(field)}
            kwargs["defaults"] = st.fixed_dictionaries(result)
            return _models_impl(st.builds(model.objects.update_or_create, **kwargs))

    # The primary key is not generated as part of the strategy, so we
    # just match against any row that has the same value for all
    # fields.
    return _models_impl(st.builds(model.objects.get_or_create, **result))
def models(
    model,  # type: Type[dm.Model]
    **field_strategies  # type: Union[st.SearchStrategy[Any], DefaultValueType]
):
    # type: (...) -> st.SearchStrategy[Any]
    """Return a strategy for examples of ``model``.

    .. warning::
        Hypothesis creates saved models. This will run inside your testing
        transaction when using the test runner, but if you use the dev console
        this will leave debris in your database.

    ``model`` must be an subclass of :class:`~django:django.db.models.Model`.
    Strategies for fields may be passed as keyword arguments, for example
    ``is_staff=st.just(False)``.

    Hypothesis can often infer a strategy based the field type and validators
    - for best results, make sure your validators are derived from Django's
    and therefore have the known types and attributes.
    Passing a keyword argument skips inference for that field; pass a strategy
    or pass ``hypothesis.extra.django.models.default_value`` to skip
    inference for that field.

    Foreign keys are not automatically derived. If they're nullable they will
    default to always being null, otherwise you always have to specify them.
    For example, examples of a Shop type with a foreign key to Company could
    be generated with::

      shop_strategy = models(Shop, company=models(Company))
    """
    note_deprecation(
        "This function is deprecated; use `hypothesis.extra.django."
        "from_model` instead.",
        since="2019-01-10",
    )
    result = {}
    for k, v in field_strategies.items():
        if not isinstance(v, DefaultValueType):
            result[k] = v
    missed = []  # type: List[Text]
    for f in model._meta.concrete_fields:
        if not (f.name in field_strategies or isinstance(f, dm.AutoField)):
            result[f.name] = from_field(f)
            if result[f.name].is_empty:
                missed.append(f.name)
    if missed:
        raise InvalidArgument(
            u"Missing arguments for mandatory field%s %s for model %s"
            % (u"s" if len(missed) > 1 else u"", u", ".join(missed), model.__name__)
        )

    for field in result:
        if model._meta.get_field(field).primary_key:
            # The primary key is generated as part of the strategy. We
            # want to find any existing row with this primary key and
            # overwrite its contents.
            kwargs = {field: result.pop(field)}
            kwargs["defaults"] = st.fixed_dictionaries(result)
            return _models_impl(st.builds(model.objects.update_or_create, **kwargs))

    # The primary key is not generated as part of the strategy, so we
    # just match against any row that has the same value for all
    # fields.
    return _models_impl(st.builds(model.objects.get_or_create, **result))
def from_form(
    form,  # type: Type[dm.Model]
    form_kwargs=None,  # type: dict
    **field_strategies  # type: Union[st.SearchStrategy[Any], InferType]
):
    # type: (...) -> st.SearchStrategy[Any]
    """Return a strategy for examples of ``form``.

    ``form`` must be an subclass of :class:`~django:django.forms.Form`.
    Strategies for fields may be passed as keyword arguments, for example
    ``is_staff=st.just(False)``.

    Hypothesis can often infer a strategy based the field type and validators,
    and will attempt to do so for any required fields.  No strategy will be
    inferred for a disabled field or field for which a keyword argument
    is passed to ``from_form()``.

    This function uses the fields of an unbound ``form`` instance to determine
    field strategies, any keyword arguments needed to instantiate the unbound
    ``form`` instance can be passed into ``from_form()`` as a dict with the
    keyword ``form_kwargs``. E.g.::

        shop_strategy = from_form(Shop, form_kwargs={"company_id": 5})

    Like for :func:`~hypothesis.strategies.builds`, you can pass
    :obj:`~hypothesis.infer` as a keyword argument to infer a strategy for
    a field which has a default value instead of using the default.
    """
    # currently unsupported:
    # ComboField
    # FilePathField
    # FileField
    # ImageField
    form_kwargs = form_kwargs or {}
    if not issubclass(form, df.BaseForm):
        raise InvalidArgument("form=%r must be a subtype of Form" % (form,))

    # Forms are a little bit different from models. Model classes have
    # all their fields defined, whereas forms may have different fields
    # per-instance. So, we ought to instantiate the form and get the
    # fields from the instance, thus we need to accept the kwargs for
    # instantiation as well as the explicitly defined strategies

    unbound_form = form(**form_kwargs)
    fields_by_name = {}
    for name, field in unbound_form.fields.items():
        if isinstance(field, df.MultiValueField):
            # PS: So this is a little strange, but MultiValueFields must
            # have their form data encoded in a particular way for the
            # values to actually be picked up by the widget instances'
            # ``value_from_datadict``.
            # E.g. if a MultiValueField named 'mv_field' has 3
            # sub-fields then the ``value_from_datadict`` will look for
            # 'mv_field_0', 'mv_field_1', and 'mv_field_2'. Here I'm
            # decomposing the individual sub-fields into the names that
            # the form validation process expects
            for i, _field in enumerate(field.fields):
                fields_by_name["%s_%d" % (name, i)] = _field
        else:
            fields_by_name[name] = field
    for name, value in sorted(field_strategies.items()):
        if value is infer:
            field_strategies[name] = from_field(fields_by_name[name])

    for name, field in sorted(fields_by_name.items()):
        if name not in field_strategies and not field.disabled:
            field_strategies[name] = from_field(field)

    return _forms_impl(
        st.builds(
            partial(form, **form_kwargs),
            data=st.fixed_dictionaries(field_strategies),  # type: ignore
        )
    )