示例#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))
示例#3
0
def from_model(
    *model: Type[dm.Model],
    **field_strategies: Union[st.SearchStrategy,
                              InferType]) -> st.SearchStrategy:
    """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)``.  In order to support models with fields named
    "model", this is a positional-only parameter.

    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 len(model) == 1:
        m_type = model[0]
    elif len(model) > 1:
        raise TypeError("Too many positional arguments")
    else:
        try:
            m_type = field_strategies.pop("model")  # type: ignore
        except KeyError:
            raise TypeError(
                "Missing required positional argument `model`") from None
        else:
            note_deprecation(
                "The `model` argument will be positional-only in a future version",
                since="2020-03-18",
            )

    if not issubclass(m_type, dm.Model):
        raise InvalidArgument("model=%r must be a subtype of Model" %
                              (model, ))

    fields_by_name = {f.name: f for f in m_type._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 m_type._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(m_type.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(m_type.objects.get_or_create, **field_strategies))
示例#4
0
def from_form(
    form: Type[df.Form],
    form_kwargs: dict = None,
    **field_strategies: Union[st.SearchStrategy, InferType]
) -> st.SearchStrategy[df.Form]:
    """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
        ))
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
        )
    )