diff options
-rw-r--r-- | README.rst | 21 | ||||
-rw-r--r-- | docs/examples.rst | 6 | ||||
-rw-r--r-- | docs/introduction.rst | 41 | ||||
-rw-r--r-- | docs/orms.rst | 47 | ||||
-rw-r--r-- | docs/recipes.rst | 40 | ||||
-rw-r--r-- | docs/reference.rst | 219 |
6 files changed, 265 insertions, 109 deletions
@@ -94,7 +94,8 @@ Usage Defining factories """""""""""""""""" -Factories declare a set of attributes used to instantiate an object. The class of the object must be defined in the FACTORY_FOR attribute: +Factories declare a set of attributes used to instantiate an object. +The class of the object must be defined in the ``target`` field of a ``class Meta:`` attribute: .. code-block:: python @@ -102,7 +103,8 @@ Factories declare a set of attributes used to instantiate an object. The class o from . import models class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User first_name = 'John' last_name = 'Doe' @@ -110,7 +112,8 @@ Factories declare a set of attributes used to instantiate an object. The class o # Another, different, factory for the same object class AdminFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User first_name = 'Admin' last_name = 'User' @@ -164,7 +167,9 @@ These "lazy" attributes can be added as follows: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User + first_name = 'Joe' last_name = 'Blow' email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower()) @@ -183,7 +188,9 @@ Unique values in a specific format (for example, e-mail addresses) can be genera .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User + email = factory.Sequence(lambda n: 'person{0}@example.com'.format(n)) >>> UserFactory().email @@ -201,7 +208,9 @@ This is handled by the ``SubFactory`` helper: .. code-block:: python class PostFactory(factory.Factory): - FACTORY_FOR = models.Post + class Meta: + target = models.Post + author = factory.SubFactory(UserFactory) diff --git a/docs/examples.rst b/docs/examples.rst index aab990a..52a5ef6 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -56,14 +56,16 @@ And now, we'll define the related factories: class AccountFactory(factory.Factory): - FACTORY_FOR = objects.Account + class Meta: + target = objects.Account username = factory.Sequence(lambda n: 'john%s' % n) email = factory.LazyAttribute(lambda o: '%s@example.org' % o.username) class ProfileFactory(factory.Factory): - FACTORY_FOR = objects.Profile + class Meta: + target = objects.Profile account = factory.SubFactory(AccountFactory) gender = factory.Iterator([objects.Profile.GENDER_MALE, objects.Profile.GENDER_FEMALE]) diff --git a/docs/introduction.rst b/docs/introduction.rst index 86e2046..6ea6b5e 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -18,10 +18,11 @@ Basic usage ----------- -Factories declare a set of attributes used to instantiate an object, whose class is defined in the FACTORY_FOR attribute: +Factories declare a set of attributes used to instantiate an object, whose class is defined in the ``class Meta``'s ``target`` attribute: - Subclass ``factory.Factory`` (or a more suitable subclass) -- Set its ``FACTORY_FOR`` attribute to the target class +- Add a ``class Meta:`` block +- Set its ``target`` attribute to the target class - Add defaults for keyword args to pass to the associated class' ``__init__`` method @@ -31,7 +32,8 @@ Factories declare a set of attributes used to instantiate an object, whose class from . import base class UserFactory(factory.Factory): - FACTORY_FOR = base.User + class Meta: + target = base.User firstname = "John" lastname = "Doe" @@ -56,7 +58,8 @@ A given class may be associated to many :class:`~factory.Factory` subclasses: .. code-block:: python class EnglishUserFactory(factory.Factory): - FACTORY_FOR = base.User + class Meta: + target = base.User firstname = "John" lastname = "Doe" @@ -64,7 +67,8 @@ A given class may be associated to many :class:`~factory.Factory` subclasses: class FrenchUserFactory(factory.Factory): - FACTORY_FOR = base.User + class Meta: + target = base.User firstname = "Jean" lastname = "Dupont" @@ -88,7 +92,8 @@ This is achieved with the :class:`~factory.Sequence` declaration: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User username = factory.Sequence(lambda n: 'user%d' % n) @@ -104,7 +109,8 @@ This is achieved with the :class:`~factory.Sequence` declaration: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User @factory.sequence def username(n): @@ -121,7 +127,8 @@ taking the object being built and returning the value for the field: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User username = factory.Sequence(lambda n: 'user%d' % n) email = factory.LazyAttribute(lambda obj: '%s@example.com' % obj.username) @@ -146,7 +153,8 @@ taking the object being built and returning the value for the field: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = models.User + class Meta: + target = models.User username = factory.Sequence(lambda n: 'user%d' % n) @@ -168,7 +176,8 @@ and update them with its own declarations: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = base.User + class Meta: + target = base.User firstname = "John" lastname = "Doe" @@ -209,13 +218,14 @@ Non-kwarg arguments Some classes take a few, non-kwarg arguments first. -This is handled by the :data:`~factory.Factory.FACTORY_ARG_PARAMETERS` attribute: +This is handled by the :data:`~factory.FactoryOptions.arg_parameters` attribute: .. code-block:: python class MyFactory(factory.Factory): - FACTORY_FOR = MyClass - FACTORY_ARG_PARAMETERS = ('x', 'y') + class Meta: + target = MyClass + arg_parameters = ('x', 'y') x = 1 y = 2 @@ -251,7 +261,8 @@ Calling a :class:`~factory.Factory` subclass will provide an object through the .. code-block:: python class MyFactory(factory.Factory): - FACTORY_FOR = MyClass + class Meta: + target = MyClass .. code-block:: pycon @@ -265,6 +276,6 @@ Calling a :class:`~factory.Factory` subclass will provide an object through the <MyClass: X (saved)> -The default strategy can be changed by setting the class-level :attr:`~factory.Factory.FACTORY_STRATEGY` attribute. +The default strategy can be changed by setting the ``class Meta`` :attr:`~factory.FactoryOptions.strategy` attribute. diff --git a/docs/orms.rst b/docs/orms.rst index c893cac..5ef8568 100644 --- a/docs/orms.rst +++ b/docs/orms.rst @@ -32,7 +32,7 @@ All factories for a Django :class:`~django.db.models.Model` should use the This class provides the following features: - * The :attr:`~factory.Factory.FACTORY_FOR` attribute also supports the ``'app.Model'`` + * The :attr:`~factory.FactoryOption.target` attribute also supports the ``'app.Model'`` syntax * :func:`~factory.Factory.create()` uses :meth:`Model.objects.create() <django.db.models.query.QuerySet.create>` * :func:`~factory.Factory._setup_next_sequence()` selects the next unused primary key value @@ -40,7 +40,12 @@ All factories for a Django :class:`~django.db.models.Model` should use the attributes, the base object will be :meth:`saved <django.db.models.Model.save>` once all post-generation hooks have run. - .. attribute:: FACTORY_DJANGO_GET_OR_CREATE + +.. class:: DjangoOptions(factory.base.FactoryOptions) + + The ``class Meta`` on a :class:`~DjangoModelFactory` supports an extra parameter: + + .. attribute:: django_get_or_create Fields whose name are passed in this list will be used to perform a :meth:`Model.objects.get_or_create() <django.db.models.query.QuerySet.get_or_create>` @@ -49,8 +54,9 @@ All factories for a Django :class:`~django.db.models.Model` should use the .. code-block:: python class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = 'myapp.User' # Equivalent to ``FACTORY_FOR = myapp.models.User`` - FACTORY_DJANGO_GET_OR_CREATE = ('username',) + class Meta: + target = 'myapp.User' # Equivalent to ``target = myapp.models.User`` + django_get_or_create = ('username',) username = 'john' @@ -80,11 +86,13 @@ All factories for a Django :class:`~django.db.models.Model` should use the .. code-block:: python class MyAbstractModelFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.MyAbstractModel - ABSTRACT_FACTORY = True + class Meta: + target = models.MyAbstractModel + abstract = True class MyConcreteModelFactory(MyAbstractModelFactory): - FACTORY_FOR = models.MyConcreteModel + class Meta: + target = models.MyConcreteModel Otherwise, factory_boy will try to get the 'next PK' counter from the abstract model. @@ -112,7 +120,8 @@ Extra fields .. code-block:: python class MyFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.MyModel + class Meta: + target = models.MyModel the_file = factory.django.FileField(filename='the_file.dat') @@ -149,7 +158,8 @@ Extra fields .. code-block:: python class MyFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.MyModel + class Meta: + target = models.MyModel the_image = factory.django.ImageField(color='blue') @@ -188,7 +198,8 @@ To work around this problem, use the :meth:`mute_signals()` decorator/context ma @factory.django.mute_signals(signals.pre_save, signals.post_save) class FooFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.Foo + class Meta: + target = models.Foo # ... @@ -241,7 +252,7 @@ factory_boy supports `MongoEngine`_-style models, through the :class:`MongoEngin * :func:`~factory.Factory.create()` builds an instance through ``__init__`` then saves it. - .. note:: If the :attr:`associated class <factory.Factory.FACTORY_FOR>` is a :class:`mongoengine.EmbeddedDocument`, + .. note:: If the :attr:`associated class <factory.FactoryOptions.target>` is a :class:`mongoengine.EmbeddedDocument`, the :meth:`~MongoEngineFactory.create` function won't "save" it, since this wouldn't make sense. This feature makes it possible to use :class:`~factory.SubFactory` to create embedded document. @@ -255,7 +266,7 @@ SQLAlchemy Factoy_boy also supports `SQLAlchemy`_ models through the :class:`SQLAlchemyModelFactory` class. -To work, this class needs an `SQLAlchemy`_ session object affected to "FACTORY_SESSION" class attribute. +To work, this class needs an `SQLAlchemy`_ session object affected to the ``Meta.sqlalchemy_session`` attribute. .. _SQLAlchemy: http://www.sqlalchemy.org/ @@ -268,7 +279,12 @@ To work, this class needs an `SQLAlchemy`_ session object affected to "FACTORY_S * :func:`~factory.Factory.create()` uses :meth:`sqlalchemy.orm.session.Session.add` * :func:`~factory.Factory._setup_next_sequence()` selects the next unused primary key value - .. attribute:: FACTORY_SESSION +.. class:: SQLAlchemyOptions(factory.base.FactoryOptions) + + In addition to the usual parameters available in :class:`class Meta <factory.base.FactoryOptions>`, + a :class:`SQLAlchemyModelFactory` also supports the following settings: + + .. attribute:: sqlalchemy_session Fields whose SQLAlchemy session object are passed will be used to communicate with the database @@ -297,8 +313,9 @@ A (very) simple exemple: class UserFactory(SQLAlchemyModelFactory): - FACTORY_FOR = User - FACTORY_SESSION = session # the SQLAlchemy session object + class Meta: + target = User + sqlalchemy_session = session # the SQLAlchemy session object id = factory.Sequence(lambda n: n) name = factory.Sequence(lambda n: u'User %d' % n) diff --git a/docs/recipes.rst b/docs/recipes.rst index 7a6bf23..917bc3c 100644 --- a/docs/recipes.rst +++ b/docs/recipes.rst @@ -26,7 +26,8 @@ use the :class:`~factory.SubFactory` declaration: from . import models class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.User + class Meta: + target = models.User first_name = factory.Sequence(lambda n: "Agent %03d" % n) group = factory.SubFactory(GroupFactory) @@ -53,7 +54,8 @@ use a :class:`~factory.RelatedFactory` declaration: # factories.py class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.User + class Meta: + target = models.User log = factory.RelatedFactory(UserLogFactory, 'user', action=models.UserLog.ACTION_CREATE) @@ -75,7 +77,8 @@ factory_boy allows to define attributes of such profiles dynamically when creati .. code-block:: python class ProfileFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = my_models.Profile + class Meta: + target = my_models.Profile title = 'Dr' # We pass in profile=None to prevent UserFactory from creating another profile @@ -83,7 +86,8 @@ factory_boy allows to define attributes of such profiles dynamically when creati user = factory.SubFactory('app.factories.UserFactory', profile=None) class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = auth_models.User + class Meta: + target = auth_models.User username = factory.Sequence(lambda n: "user_%d" % n) @@ -145,12 +149,14 @@ hook: # factories.py class GroupFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.Group + class Meta: + target = models.Group name = factory.Sequence(lambda n: "Group #%s" % n) class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.User + class Meta: + target = models.User name = "John Doe" @@ -200,17 +206,20 @@ If more links are needed, simply add more :class:`RelatedFactory` declarations: # factories.py class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.User + class Meta: + target = models.User name = "John Doe" class GroupFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.Group + class Meta: + target = models.Group name = "Admins" class GroupLevelFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.GroupLevel + class Meta: + target = models.GroupLevel user = factory.SubFactory(UserFactory) group = factory.SubFactory(GroupFactory) @@ -273,20 +282,23 @@ Here, we want: # factories.py class CountryFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.Country + class Meta: + target = models.Country name = factory.Iterator(["France", "Italy", "Spain"]) lang = factory.Iterator(['fr', 'it', 'es']) class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.User + class Meta: + target = models.User name = "John" lang = factory.SelfAttribute('country.lang') country = factory.SubFactory(CountryFactory) class CompanyFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.Company + class Meta: + target = models.Company name = "ACME, Inc." country = factory.SubFactory(CountryFactory) @@ -302,7 +314,9 @@ default :meth:`Model.objects.create() <django.db.models.query.QuerySet.create>` .. code-block:: python class UserFactory(factory.DjangoModelFactory): - FACTORY_FOR = UserenaSignup + class Meta: + target = UserenaSignup + username = "l7d8s" email = "my_name@example.com" password = "my_password" diff --git a/docs/reference.rst b/docs/reference.rst index 53584a0..f19b44e 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -11,37 +11,54 @@ For internals and customization points, please refer to the :doc:`internals` sec The :class:`Factory` class -------------------------- -.. class:: Factory +.. class:: FactoryOptions + + .. versionadded:: 2.4.0 + + A :class:`Factory`'s behaviour can be tuned through a few settings. + + For convenience, they are declared in a single ``class Meta`` attribute: - The :class:`Factory` class is the base of factory_boy features. + .. code-block:: python - It accepts a few specific attributes (must be specified on class declaration): + class MyFactory(factory.Factory): + class Meta: + target = MyObject + abstract = False - .. attribute:: FACTORY_FOR + .. attribute:: target This optional attribute describes the class of objects to generate. If unset, it will be inherited from parent :class:`Factory` subclasses. - .. attribute:: ABSTRACT_FACTORY + .. versionadded:: 2.4.0 + + .. attribute:: abstract This attribute indicates that the :class:`Factory` subclass should not be used to generate objects, but instead provides some extra defaults. It will be automatically set to ``True`` if neither the :class:`Factory` - subclass nor its parents define the :attr:`~Factory.FACTORY_FOR` attribute. + subclass nor its parents define the :attr:`~FactoryOptions.target` attribute. + + .. warning:: This flag is reset to ``False`` When a :class:`Factory` subclasses + another one if a :attr:`~FactoryOptions.target` is set. + + .. versionadded:: 2.4.0 - .. attribute:: FACTORY_ARG_PARAMETERS + .. attribute:: arg_parameters Some factories require non-keyword arguments to their :meth:`~object.__init__`. - They should be listed, in order, in the :attr:`FACTORY_ARG_PARAMETERS` + They should be listed, in order, in the :attr:`arg_parameters` attribute: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User - FACTORY_ARG_PARAMETERS = ('login', 'email') + class Meta: + target = User + arg_parameters = ('login', 'email') login = 'john' email = factory.LazyAttribute(lambda o: '%s@example.com' % o.login) @@ -53,22 +70,25 @@ The :class:`Factory` class <User: john> >>> User('john', 'john@example.com', firstname="John") # actual call - .. attribute:: FACTORY_HIDDEN_ARGS + .. versionadded:: 2.4.0 + + .. attribute:: hidden_args While writing a :class:`Factory` for some object, it may be useful to have general fields helping defining others, but that should not be passed to the target class; for instance, a field named 'now' that would hold a reference time used by other objects. - Factory fields whose name are listed in :attr:`FACTORY_HIDDEN_ARGS` will + Factory fields whose name are listed in :attr:`hidden_args` will be removed from the set of args/kwargs passed to the underlying class; they can be any valid factory_boy declaration: .. code-block:: python class OrderFactory(factory.Factory): - FACTORY_FOR = Order - FACTORY_HIDDEN_ARGS = ('now',) + class Meta: + target = Order + hidden_args = ('now',) now = factory.LazyAttribute(lambda o: datetime.datetime.utcnow()) started_at = factory.LazyAttribute(lambda o: o.now - datetime.timedelta(hours=1)) @@ -83,6 +103,55 @@ The :class:`Factory` class >>> OrderFactory(now=datetime.datetime(2013, 4, 1, 10)) <Order: started 2013-04-01 09:00:00, paid 2013-04-01 09:10:00> + .. versionadded:: 2.4.0 + + +.. class:: Factory + + .. note:: In previous versions, the fields of :class:`class Meta <factory.FactoryOptions>` were + defined as class attributes on :class:`Factory`. This is now deprecated and will be removed + in 2.5.0. + + .. attribute:: FACTORY_FOR + + .. deprecated:: 2.4.0 + See :attr:`FactoryOptions.target`. + + .. attribute:: ABSTRACT_FACTORY + + .. deprecated:: 2.4.0 + See :attr:`FactoryOptions.abstract`. + + .. attribute:: FACTORY_ARG_PARAMETERS + + .. deprecated:: 2.4.0 + See :attr:`FactoryOptions.arg_parameters`. + + .. attribute:: FACTORY_HIDDEN_ARGS + + .. deprecated:: 2.4.0 + See :attr:`FactoryOptions.hidden_args`. + + + **Class-level attributes:** + + .. attribute:: _meta + + .. versionadded:: 2.4.0 + + The :class:`FactoryOptions` instance attached to a :class:`Factory` class is available + as a :attr:`_meta` attribute. + + .. attribute:: _options_class + + .. versionadded:: 2.4.0 + + If a :class:`Factory` subclass needs to define additional, extra options, it has to + provide a custom :class:`FactoryOptions` subclass. + + A pointer to that custom class should be provided as :attr:`_options_class` so that + the :class:`Factory`-building metaclass can use it instead. + **Base functions:** @@ -162,7 +231,7 @@ The :class:`Factory` class The :meth:`_adjust_kwargs` extension point allows for late fields tuning. It is called once keyword arguments have been resolved and post-generation - items removed, but before the :attr:`FACTORY_ARG_PARAMETERS` extraction + items removed, but before the :attr:`~FactoryOptions.arg_parameters` extraction phase. .. code-block:: python @@ -194,7 +263,7 @@ The :class:`Factory` class .. OHAI_VIM* This class method is called whenever a new instance needs to be built. - It receives the target class (provided to :attr:`FACTORY_FOR`), and + It receives the target class (provided to :attr:`~FactoryOptions.target`), and the positional and keyword arguments to use for the class once all has been computed. @@ -214,7 +283,8 @@ The :class:`Factory` class .. code-block:: python class BaseBackendFactory(factory.Factory): - ABSTRACT_FACTORY = True # Optional + class Meta: + abstract = True # Optional def _create(cls, target_class, *args, **kwargs): obj = target_class(*args, **kwargs) @@ -254,7 +324,7 @@ The :class:`Factory` class >>> SomeFactory._next_sequence 4 - Since subclasses of a non-:attr:`abstract <factory.Factory.ABSTRACT_FACTORY>` + Since subclasses of a non-:attr:`abstract <factory.FactoryOptions.abstract>` :class:`~factory.Factory` share the same sequence counter, special care needs to be taken when resetting the counter of such a subclass. @@ -293,7 +363,7 @@ factory_boy supports two main strategies for generating instances, plus stubs. but not persisted to any datastore. It is usually a simple call to the :meth:`~object.__init__` method of the - :attr:`~Factory.FACTORY_FOR` class. + :attr:`~FactoryOptions.target` class. .. data:: CREATE_STRATEGY @@ -316,7 +386,7 @@ factory_boy supports two main strategies for generating instances, plus stubs. when using the ``create`` strategy. That policy will be used if the - :attr:`associated class <Factory.FACTORY_FOR>` has an ``objects`` + :attr:`associated class <FactoryOptions.target>` has an ``objects`` attribute *and* the :meth:`~Factory._create` classmethod of the :class:`Factory` wasn't overridden. @@ -337,7 +407,7 @@ factory_boy supports two main strategies for generating instances, plus stubs. .. data:: STUB_STRATEGY The 'stub' strategy is an exception in the factory_boy world: it doesn't return - an instance of the :attr:`~Factory.FACTORY_FOR` class, and actually doesn't + an instance of the :attr:`~FactoryOptions.target` class, and actually doesn't require one to be present. Instead, it returns an instance of :class:`StubObject` whose attributes have been @@ -359,7 +429,7 @@ factory_boy supports two main strategies for generating instances, plus stubs. .. class:: StubFactory(Factory) - An :attr:`abstract <Factory.ABSTRACT_FACTORY>` :class:`Factory`, + An :attr:`abstract <FactoryOptions.abstract>` :class:`Factory`, with a default strategy set to :data:`STUB_STRATEGY`. @@ -414,7 +484,8 @@ accept the object being built as sole argument, and return a value. .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User username = 'john' email = factory.LazyAttribute(lambda o: '%s@example.com' % o.username) @@ -449,7 +520,8 @@ return value of the method: .. code-block:: python class UserFactory(factory.Factory) - FACTORY_FOR = User + class Meta: + target = User name = u"Jean" @@ -487,7 +559,8 @@ This declaration takes a single argument, a function accepting a single paramete .. code-block:: python class UserFactory(factory.Factory) - FACTORY_FOR = User + class Meta: + target = User phone = factory.Sequence(lambda n: '123-555-%04d' % n) @@ -512,7 +585,8 @@ be the sequence counter - this might be confusing: .. code-block:: python class UserFactory(factory.Factory) - FACTORY_FOR = User + class Meta: + target = User @factory.sequence def phone(n): @@ -537,7 +611,8 @@ The sequence counter is shared across all :class:`Sequence` attributes of the .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User phone = factory.Sequence(lambda n: '%04d' % n) office = factory.Sequence(lambda n: 'A23-B%03d' % n) @@ -561,7 +636,8 @@ sequence counter is shared: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User phone = factory.Sequence(lambda n: '123-555-%04d' % n) @@ -596,7 +672,8 @@ class-level value. .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User uid = factory.Sequence(int) @@ -631,7 +708,8 @@ It takes a single argument, a function whose two parameters are, in order: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User login = 'john' email = factory.LazyAttributeSequence(lambda o, n: '%s@s%d.example.com' % (o.login, n)) @@ -655,7 +733,8 @@ handles more complex cases: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User login = 'john' @@ -692,7 +771,8 @@ The :class:`SubFactory` attribute should be called with: .. code-block:: python class FooFactory(factory.Factory): - FACTORY_FOR = Foo + class Meta: + target = Foo bar = factory.SubFactory(BarFactory) # Not BarFactory() @@ -705,7 +785,8 @@ Definition # A standard factory class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User # Various fields first_name = 'John' @@ -714,7 +795,8 @@ Definition # A factory for an object with a 'User' field class CompanyFactory(factory.Factory): - FACTORY_FOR = Company + class Meta: + target = Company name = factory.Sequence(lambda n: 'FactoryBoyz' + 'z' * n) @@ -794,13 +876,15 @@ This issue can be handled by passing the absolute import path to the target .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User username = 'john' main_group = factory.SubFactory('users.factories.GroupFactory') class GroupFactory(factory.Factory): - FACTORY_FOR = Group + class Meta: + target = Group name = "MyGroup" owner = factory.SubFactory(UserFactory) @@ -828,7 +912,8 @@ That declaration takes a single argument, a dot-delimited path to the attribute .. code-block:: python class UserFactory(factory.Factory) - FACTORY_FOR = User + class Meta: + target = User birthdate = factory.Sequence(lambda n: datetime.date(2000, 1, 1) + datetime.timedelta(days=n)) birthmonth = factory.SelfAttribute('birthdate.month') @@ -854,13 +939,15 @@ gains an "upward" semantic through the double-dot notation, as used in Python im .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User language = 'en' class CompanyFactory(factory.Factory): - FACTORY_FOR = Company + class Meta: + target = Company country = factory.SubFactory(CountryFactory) owner = factory.SubFactory(UserFactory, language=factory.SelfAttribute('..country.language')) @@ -888,7 +975,8 @@ through the :attr:`~containers.LazyStub.factory_parent` attribute of the passed- .. code-block:: python class CompanyFactory(factory.Factory): - FACTORY_FOR = Company + class Meta: + target = Company country = factory.SubFactory(CountryFactory) owner = factory.SubFactory(UserFactory, language=factory.LazyAttribute(lambda user: user.factory_parent.country.language), @@ -966,7 +1054,8 @@ adequate value. .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User # CATEGORY_CHOICES is a list of (key, title) tuples category = factory.Iterator(User.CATEGORY_CHOICES, getter=lambda c: c[0]) @@ -987,7 +1076,8 @@ use the :func:`iterator` decorator: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User @factory.iterator def name(): @@ -1030,7 +1120,8 @@ with the :class:`Dict` and :class:`List` attributes: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User is_superuser = False roles = factory.Dict({ @@ -1066,7 +1157,8 @@ with the :class:`Dict` and :class:`List` attributes: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User flags = factory.List([ 'user', @@ -1113,7 +1205,8 @@ For instance, a :class:`PostGeneration` hook is declared as ``post``: .. code-block:: python class SomeFactory(factory.Factory): - FACTORY_FOR = SomeObject + class Meta: + target = SomeObject @post_generation def post(self, create, extracted, **kwargs): @@ -1128,7 +1221,7 @@ When calling the factory, some arguments will be extracted for this method: - Any argument starting with ``post__XYZ`` will be extracted, its ``post__`` prefix removed, and added to the kwargs passed to the post-generation hook. -Extracted arguments won't be passed to the :attr:`~Factory.FACTORY_FOR` class. +Extracted arguments won't be passed to the :attr:`~FactoryOptions.target` class. Thus, in the following call: @@ -1142,7 +1235,7 @@ Thus, in the following call: ) The ``post`` hook will receive ``1`` as ``extracted`` and ``{'y': 3, 'z__t': 42}`` -as keyword arguments; ``{'post_x': 2}`` will be passed to ``SomeFactory.FACTORY_FOR``. +as keyword arguments; ``{'post_x': 2}`` will be passed to ``SomeFactory._meta.target``. RelatedFactory @@ -1184,7 +1277,8 @@ RelatedFactory .. code-block:: python class FooFactory(factory.Factory): - FACTORY_FOR = Foo + class Meta: + target = Foo bar = factory.RelatedFactory(BarFactory) # Not BarFactory() @@ -1192,13 +1286,15 @@ RelatedFactory .. code-block:: python class CityFactory(factory.Factory): - FACTORY_FOR = City + class Meta: + target = City capital_of = None name = "Toronto" class CountryFactory(factory.Factory): - FACTORY_FOR = Country + class Meta: + target = Country lang = 'fr' capital_city = factory.RelatedFactory(CityFactory, 'capital_of', name="Paris") @@ -1260,7 +1356,8 @@ as ``callable(obj, create, extracted, **kwargs)``, where: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User login = 'john' make_mbox = factory.PostGeneration( @@ -1280,7 +1377,8 @@ A decorator is also provided, decorating a single method accepting the same .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User login = 'john' @@ -1316,7 +1414,7 @@ PostGenerationMethodCall .. attribute:: method_name - The name of the method to call on the :attr:`~Factory.FACTORY_FOR` object + The name of the method to call on the :attr:`~FactoryOptions.target` object .. attribute:: args @@ -1340,7 +1438,8 @@ attribute like below: .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User username = 'user' password = factory.PostGenerationMethodCall('set_password', @@ -1390,7 +1489,8 @@ factory during instantiation. .. code-block:: python class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = User + class Meta: + target = User username = 'user' password = factory.PostGenerationMethodCall('set_password', @@ -1404,7 +1504,8 @@ example, if we declared the ``password`` attribute like the following, .. code-block:: python class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User username = 'user' password = factory.PostGenerationMethodCall('set_password', '', 'sha1') @@ -1467,7 +1568,8 @@ Lightweight factory declaration # This is equivalent to: class UserFactory(factory.Factory): - FACTORY_FOR = User + class Meta: + target = User login = 'john' email = factory.LazyAttribute(lambda u: '%s@example.com' % u.login) @@ -1486,7 +1588,8 @@ Lightweight factory declaration # This is equivalent to: class UserFactory(factory.django.DjangoModelFactory): - FACTORY_FOR = models.User + class Meta: + target = models.User login = 'john' email = factory.LazyAttribute(lambda u: '%s@example.com' % u.login) |