summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/changelog.rst1
-rw-r--r--docs/reference.rst31
-rw-r--r--factory/base.py8
-rw-r--r--factory/containers.py13
-rw-r--r--tests/test_using.py16
5 files changed, 64 insertions, 5 deletions
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 100952c..80074ae 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -14,6 +14,7 @@ ChangeLog
- Add support for ``get_or_create`` in :class:`~factory.DjangoModelFactory`,
through :attr:`~factory.DjangoModelFactory.FACTORY_DJANGO_GET_OR_CREATE`.
- Add support for :mod:`~factory.fuzzy` attribute definitions.
+ - The :class:`Sequence` counter can be overridden when calling a generating function
*Removed:*
diff --git a/docs/reference.rst b/docs/reference.rst
index a2af327..13220b0 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -502,6 +502,37 @@ sequence counter is shared:
'123-555-0003'
+Forcing a sequence counter
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If a specific value of the sequence counter is required for one instance, the
+``__sequence`` keyword argument should be passed to the factory method.
+
+This will force the sequence counter during the call, without altering the
+class-level value.
+
+.. code-block:: python
+
+ class UserFactory(factory.Factory):
+ FACTORY_FOR = User
+
+ uid = factory.Sequence(int)
+
+.. code-block:: pycon
+
+ >>> UserFactory()
+ <User: 0>
+ >>> UserFactory()
+ <User: 1>
+ >>> UserFactory(__sequence=42)
+ <User: 42>
+
+
+.. warning:: The impact of setting ``__sequence=n`` on a ``_batch`` call is
+ undefined. Each generated instance may share a same counter, or
+ use incremental values starting from the forced value.
+
+
LazyAttributeSequence
"""""""""""""""""""""
diff --git a/factory/base.py b/factory/base.py
index 13a0623..25f4714 100644
--- a/factory/base.py
+++ b/factory/base.py
@@ -282,7 +282,13 @@ class BaseFactory(object):
applicable; the current list of computed attributes is available
to the currently processed object.
"""
- return containers.AttributeBuilder(cls, extra).build(create)
+ force_sequence = None
+ if extra:
+ force_sequence = extra.pop('__sequence', None)
+ return containers.AttributeBuilder(cls, extra).build(
+ create=create,
+ force_sequence=force_sequence,
+ )
@classmethod
def declarations(cls, extra_defs=None):
diff --git a/factory/containers.py b/factory/containers.py
index e02f9f9..ee2ad82 100644
--- a/factory/containers.py
+++ b/factory/containers.py
@@ -236,16 +236,21 @@ class AttributeBuilder(object):
attrs_with_subfields, self._attrs)
def has_subfields(self, value):
- return isinstance(value, declarations.SubFactory)
+ return isinstance(value, declarations.ParameteredAttribute)
- def build(self, create):
+ def build(self, create, force_sequence=None):
"""Build a dictionary of attributes.
Args:
create (bool): whether to 'build' or 'create' the subfactories.
+ force_sequence (int or None): if set to an int, use this value for
+ the sequence counter; don't advance the related counter.
"""
# Setup factory sequence.
- self.factory.sequence = self.factory._generate_next_sequence()
+ if force_sequence is None:
+ sequence = self.factory._generate_next_sequence()
+ else:
+ sequence = force_sequence
# Parse attribute declarations, wrapping SubFactory and
# OrderedDeclaration.
@@ -253,7 +258,7 @@ class AttributeBuilder(object):
for k, v in self._attrs.items():
if isinstance(v, declarations.OrderedDeclaration):
v = OrderedDeclarationWrapper(v,
- sequence=self.factory.sequence,
+ sequence=sequence,
create=create,
extra=self._subfields.get(k, {}),
)
diff --git a/tests/test_using.py b/tests/test_using.py
index dde0ba7..def49e4 100644
--- a/tests/test_using.py
+++ b/tests/test_using.py
@@ -346,6 +346,22 @@ class UsingFactoryTestCase(unittest.TestCase):
self.assertEqual('one43', test_object1.one)
self.assertEqual('two43', test_object1.two)
+ def test_sequence_override(self):
+ class TestObjectFactory(factory.Factory):
+ FACTORY_FOR = TestObject
+
+ one = factory.Sequence(lambda n: 'one%d' % n)
+
+ o1 = TestObjectFactory()
+ o2 = TestObjectFactory()
+ o3 = TestObjectFactory(__sequence=42)
+ o4 = TestObjectFactory()
+
+ self.assertEqual('one0', o1.one)
+ self.assertEqual('one1', o2.one)
+ self.assertEqual('one42', o3.one)
+ self.assertEqual('one2', o4.one)
+
def test_custom_create(self):
class TestModelFactory(factory.Factory):
FACTORY_FOR = TestModel