Source code for boogie.testing.factories

import inspect

import factory as _factory
from factory import DjangoModelFactory, Factory
from factory import declarations
from factory.declarations import BaseDeclaration
from faker import Factory as FakeFactory
from model_mommy.mommy import Mommy

fake = FakeFactory.create()

FactoryMeta = type(DjangoModelFactory)


def __getitem__(self, idx):
    if isinstance(idx, slice):
        pass
    return ...


FactoryMeta.__getitem__ = __getitem__


class BoogieMommy(Mommy):
    """
    Base for Boogie Model Mommy classes.
    """

    attr_mapping = {}
    type_mapping = {}


#
# Declarations
#
class ImplicitDeclaration(BaseDeclaration):
    def __init__(self):
        pass


#
# Factory function
#
[docs]def factory(model, **kwargs): """ Creates a factory boy factory class """ ns = {"Meta": type("Meta", (), {"model": model})} # Handle explicitly declared values for k, v in kwargs: ns[k] = explicit_declaration(model, k, v) # Create mommy instance to help with automatic value generation mommy = Mommy(model) # Create implicit declarations for field in model._meta.fields: if not requires_declaration(model, field.name, ns): continue ns[field.name] = implicit_declaration(model, field.name, ns, mommy) return type(model.__name__ + "Factory", (DjangoModelFactory,), ns)
def explicit_declaration(model, name, value): """ Return a Declaration instance that implements an explicitly defined field for a model. Args: model: Model class name: Name of the field in the model value: Value explicitly passed by the user """ if issubclass(value, BaseDeclaration): return value elif isinstance(value, type) and issubclass(value, Factory): return _factory.SubFactory(value) elif callable(value): if has_no_args(value): return _factory.LazyFunction(value) else: return _factory.LazyAttribute(value) elif isinstance(value, str): return _factory.LazyAttribute(lambda x: value.format(model=x)) else: return value def requires_declaration(model, name, definitions): """ Return True if explicit generation of given field is required during model instantiation. Args: model: Model class name: Model field name definitions: A map of names of all explicitly defined fields to their corresponding defined values. """ field = model._meta.get_field(name) if field.has_default() or field.auto_created: return False if field in definitions: return False return True def implicit_declaration(model, name, definitions, mommy): """ Creates an implicit declaration for the field. Receives the same arguments as :func:`requires_declaration`, but returns a declaration instance. """ field = model._meta.get_field(name) try: faker = getattr(fake, name) return declarations.LazyFunction(faker) except AttributeError: generator = lambda: mommy.generate_value(field, commit=False) return declarations.LazyFunction(generator) def has_no_args(func): """ Return True if function is called with no positional args. """ try: spec = inspect.getfullargspec(func) except TypeError: return has_no_args(func.__call__) return bool(spec.args)