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))
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))
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 ) )