summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lasher <chris.lasher@gmail.com>2013-03-07 15:23:04 -0500
committerRaphaël Barrois <raphael.barrois@polyconseil.fr>2013-03-11 17:16:30 +0100
commitc5ea364df829974aaee1d84cf70d96a125afe464 (patch)
treedbc472352efb38342d57ed2e0e76b4179aec311f
parent114ac649e448e97a210cf8dccc6ba50278645ce6 (diff)
downloadfactory-boy-c5ea364df829974aaee1d84cf70d96a125afe464.tar
factory-boy-c5ea364df829974aaee1d84cf70d96a125afe464.tar.gz
Merge documentation for PostGenerationMethodCall.
This merges in changes provided by gotgenes to the previous PostGeneration documentation to the new documentation provided by rbarrois. This documentation relates to the new functionality of overriding default arguments to declarations of PostGenerationMethodCall. Signed-off-by: Raphaël Barrois <raphael.barrois@polyconseil.fr>
-rw-r--r--docs/reference.rst117
1 files changed, 93 insertions, 24 deletions
diff --git a/docs/reference.rst b/docs/reference.rst
index 03023fc..70ca38a 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -863,6 +863,7 @@ Some objects expect additional method calls or complex processing for proper def
For instance, a ``User`` may need to have a related ``Profile``, where the ``Profile`` is built from the ``User`` object.
To support this pattern, factory_boy provides the following tools:
+ - :class:`PostGenerationMethodCall`: allows you to hook a particular attribute to a function call
- :class:`PostGeneration`: this class allows calling a given function with the generated object as argument
- :func:`post_generation`: decorator performing the same functions as :class:`PostGeneration`
- :class:`RelatedFactory`: this builds or creates a given factory *after* building/creating the first Factory.
@@ -1047,60 +1048,121 @@ PostGenerationMethodCall
.. class:: PostGenerationMethodCall(method_name, extract_prefix=None, *args, **kwargs)
-.. OHAI_VIM*
+ .. OHAI_VIM*
+
+ The :class:`PostGenerationMethodCall` declaration will call a method on
+ the generated object just after instantiation. This declaration class
+ provides a friendly means of generating attributes of a factory instance
+ during initialization. The declaration is created using the following arguments:
+
+ .. attribute:: method_name
+
+ The name of the method to call on the :attr:`~Factory.FACTORY_FOR` object
-The :class:`PostGenerationMethodCall` declaration will call a method on the
-generated object just after it being called.
+ .. attribute:: extract_prefix
-Its sole argument is the name of the method to call.
-Extra arguments and keyword arguments for the target method may also be provided.
+ If a string, the keyword argument prefix by which the field will get its
+ overriding arguments. If ``None``, defaults to the name of the attribute.
-Once the object has been generated, the method will be called, with arguments
-taken from either the :class:`PostGenerationMethodCall` or prefix-based values:
+ .. deprecated:: 1.3.0
+ Will be removed in 2.0.0
-- If a value was extracted from kwargs (i.e an argument for the name the
- :class:`PostGenerationMethodCall` was declared under):
+ .. attribute:: args
- - If the declaration mentionned zero or one argument, the value is passed
- directly to the method
- - If the declaration used two or more arguments, the value is passed as
- ``*args`` to the method
+ The default set of unnamed arguments to pass to the method given in
+ :attr:`method_name`
-- Otherwise, the arguments used when declaring the :class:`PostGenerationMethodCall`
- are used
+ .. attrinbute:: kwargs
-- Keywords extracted from the factory arguments are merged into the defaults
- present in the :class:`PostGenerationMethodCall` declaration.
+ The default set of keyword arguments to pass to the method given in
+ :attr:`method_name`
+
+Once the factory instance has been generated, the method specified in
+:attr:`~PostGenerationMethodCall.method_name` will be called on the generated object
+with any arguments specified in the :class:`PostGenerationMethodCall` declaration, by
+default.
+
+For example, to set a default password on a generated User instance
+during instantiation, we could make a declaration for a ``password``
+attribute like below:
.. code-block:: python
class UserFactory(factory.Factory):
FACTORY_FOR = User
- password = factory.PostGenerationMethodCall('set_password', password='')
+ username = 'user'
+ password = factory.PostGenerationMethodCall('set_password',
+ 'defaultpassword')
+
+When we instantiate a user from the ``UserFactory``, the factory
+will create a password attribute by calling ``User.set_password('defaultpassword')``.
+Thus, by default, our users will have a password set to ``'defaultpassword'``.
.. code-block:: pycon
- >>> UserFactory() # Calls user.set_password(password='')
- >>> UserFactory(password='test') # Calls user.set_password('test')
- >>> UserFactory(password__disabled=True) # Calls user.set_password(password='', disabled=True)
+ >>> u = UserFactory() # Calls user.set_password('defaultpassword')
+ >>> u.check_password('defaultpassword')
+ True
+
+If the :class:`PostGenerationMethodCall` declaration contained no
+arguments or one argument, an overriding the value can be passed
+directly to the method through a keyword argument matching the attribute name.
+For example we can override the default password specified in the declaration
+above by simply passing in the desired password as a keyword argument to the
+factory during instantiation.
+
+.. code-block:: pycon
+
+ >>> other_u = UserFactory(password='different') # Calls user.set_password('different')
+ >>> other_u.check_password('defaultpassword')
+ False
+ >>> other_u.check_password('different')
+ True
+
+.. note:: For Django models, unless the object method called by
+ :class:`PostGenerationMethodCall` saves the object back to the
+ database, we will have to explicitly remember to save the object back
+ if we performed a ``create()``.
+
+ .. code-block:: pycon
+
+ >>> u = UserFactory.create() # u.password has not been saved back to the database
+ >>> u.save() # we must remember to do it ourselves
-When the :class:`PostGenerationMethodCall` declaration uses two or more arguments,
-the extracted value must be iterable:
+ We can avoid this by subclassing from :class:`DjangoModelFactory`,
+ instead, e.g.,
+
+ .. code-block:: python
+
+ class UserFactory(factory.DjangoModelFactory):
+ FACTORY_FOR = User
+
+ username = 'user'
+ password = factory.PostGenerationMethodCall('set_password',
+ 'defaultpassword')
+
+
+If instead the :class:`PostGenerationMethodCall` declaration uses two or
+more positional arguments, the overriding value must be an iterable. For
+example, if we declared the ``password`` attribute like the following,
.. code-block:: python
class UserFactory(factory.Factory):
FACTORY_FOR = User
+ username = 'user'
password = factory.PostGenerationMethodCall('set_password', '', 'sha1')
+then we must be cautious to pass in an iterable for the ``password``
+keyword argument when creating an instance from the factory:
+
.. code-block:: pycon
>>> UserFactory() # Calls user.set_password('', 'sha1')
>>> UserFactory(password=('test', 'md5')) # Calls user.set_password('test', 'md5')
- >>> UserFactory(password__disabled=True) # Calls user.set_password('', 'sha1', disabled=True)
>>> # Always pass in a good iterable:
>>> UserFactory(password=('test',)) # Calls user.set_password('test')
@@ -1116,6 +1178,13 @@ the extracted value must be iterable:
value to the :class:`PostGenerationMethodCall` declaration
(``PostGenerationMethodCall('method', 'x', 'y_that_is_the_default')``)
+Keywords extracted from the factory arguments are merged into the
+defaults present in the :class:`PostGenerationMethodCall` declaration.
+
+.. code-block:: pycon
+
+ >>> UserFactory(password__disabled=True) # Calls user.set_password('', 'sha1', disabled=True)
+
Module-level functions
----------------------