summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphaël Barrois <raphael.barrois@polytechnique.org>2014-11-16 22:34:29 +0100
committerRaphaël Barrois <raphael.barrois@polytechnique.org>2014-11-16 22:34:29 +0100
commit13d310fa14f4e4b9a559f8b7887f2a2492357013 (patch)
tree4ce6820ef321dceb9b6e1e687534b622e335f444
parent827af8f13a1b768a75264874c73cc0e620177262 (diff)
downloadfactory-boy-13d310fa14f4e4b9a559f8b7887f2a2492357013.tar
factory-boy-13d310fa14f4e4b9a559f8b7887f2a2492357013.tar.gz
Remove automagic pk-based sequence setup
Related to issues #78, #92, #103, #111, #153, #170 The default value of all sequences is now 0; the automagic ``_setup_next_sequence`` behavior of Django/SQLAlchemy has been removed. This feature's only goal was to allow the following scenario: 1. Run a Python script that uses MyFactory.create() a couple of times (with a unique field based on the sequence counter) 2. Run the same Python script a second time Without the magical ``_setup_next_sequence``, the Sequence counter would be set to 0 at the beginning of each script run, so both runs would generate objects with the same values for the unique field ; thus conflicting and crashing. The above behavior having only a very limited use and bringing various issues (hitting the database on ``build()``, problems with non-integer or composite primary key columns, ...), it has been removed. It could still be emulated through custom ``_setup_next_sequence`` methods, or by calling ``MyFactory.reset_sequence()``.
-rw-r--r--docs/changelog.rst13
-rw-r--r--docs/orms.rst2
-rw-r--r--factory/alchemy.py12
-rw-r--r--factory/django.py15
-rw-r--r--tests/test_alchemy.py22
-rw-r--r--tests/test_django.py40
-rw-r--r--tests/test_using.py20
7 files changed, 50 insertions, 74 deletions
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 7d77f7f..018ec60 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -2,6 +2,17 @@ ChangeLog
=========
+.. _v2.5.0:
+
+2.5.0 (master)
+--------------
+
+*Deprecation:*
+
+ - Remove deprecated features from :ref:`v2.4.0`
+ - Remove the auto-magical sequence setup (based on the latest primary key value in the database) for Django and SQLAlchemy;
+ this relates to issues :issue:`170`, :issue:`153`, :issue:`111`, :issue:`103`, :issue:`92`, :issue:`78`.
+
.. _v2.4.1:
2.4.1 (2014-06-23)
@@ -19,7 +30,7 @@ ChangeLog
*New:*
- Add support for :attr:`factory.fuzzy.FuzzyInteger.step`, thanks to `ilya-pirogov <https://github.com/ilya-pirogov>`_ (:issue:`120`)
- - Add :meth:`~factory.django.mute_signals` decorator to temporarily disable some signals, thanks to `ilya-pirogov <https://github.com>`_ (:issue:`122`)
+ - Add :meth:`~factory.django.mute_signals` decorator to temporarily disable some signals, thanks to `ilya-pirogov <https://github.com/ilya-pirogov>`_ (:issue:`122`)
- Add :class:`~factory.fuzzy.FuzzyFloat` (:issue:`124`)
- Declare target model and other non-declaration fields in a ``class Meta`` section.
diff --git a/docs/orms.rst b/docs/orms.rst
index 2aa27b2..88d49e9 100644
--- a/docs/orms.rst
+++ b/docs/orms.rst
@@ -35,7 +35,6 @@ All factories for a Django :class:`~django.db.models.Model` should use the
* The :attr:`~factory.FactoryOptions.model` 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
* When using :class:`~factory.RelatedFactory` or :class:`~factory.PostGeneration`
attributes, the base object will be :meth:`saved <django.db.models.Model.save>`
once all post-generation hooks have run.
@@ -284,7 +283,6 @@ To work, this class needs an `SQLAlchemy`_ session object affected to the :attr:
This class provides the following features:
* :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
diff --git a/factory/alchemy.py b/factory/alchemy.py
index 3c91411..2cd28bb 100644
--- a/factory/alchemy.py
+++ b/factory/alchemy.py
@@ -44,18 +44,6 @@ class SQLAlchemyModelFactory(base.Factory):
})
@classmethod
- def _setup_next_sequence(cls, *args, **kwargs):
- """Compute the next available PK, based on the 'pk' database field."""
- session = cls._meta.sqlalchemy_session
- model = cls._meta.model
- pk = getattr(model, model.__mapper__.primary_key[0].name)
- max_pk = session.query(max(pk)).one()[0]
- if isinstance(max_pk, int):
- return max_pk + 1 if max_pk else 1
- else:
- return 1
-
- @classmethod
def _create(cls, model_class, *args, **kwargs):
"""Create an instance of the model, and save it to the database."""
session = cls._meta.sqlalchemy_session
diff --git a/factory/django.py b/factory/django.py
index 2b6c463..c58a6e2 100644
--- a/factory/django.py
+++ b/factory/django.py
@@ -110,21 +110,6 @@ class DjangoModelFactory(base.Factory):
return model_class.objects
@classmethod
- def _setup_next_sequence(cls):
- """Compute the next available PK, based on the 'pk' database field."""
-
- model = cls._get_model_class() # pylint: disable=E1101
- manager = cls._get_manager(model)
-
- try:
- return 1 + manager.values_list('pk', flat=True
- ).order_by('-pk')[0]
- except (IndexError, TypeError):
- # IndexError: No instance exist yet
- # TypeError: pk isn't an integer type
- return 1
-
- @classmethod
def _get_or_create(cls, model_class, *args, **kwargs):
"""Create an instance of the model through objects.get_or_create."""
manager = cls._get_manager(model_class)
diff --git a/tests/test_alchemy.py b/tests/test_alchemy.py
index b9222eb..2deb418 100644
--- a/tests/test_alchemy.py
+++ b/tests/test_alchemy.py
@@ -88,18 +88,18 @@ class SQLAlchemyPkSequenceTestCase(unittest.TestCase):
StandardFactory.reset_sequence()
std2 = StandardFactory.create()
- self.assertEqual('foo2', std2.foo)
- self.assertEqual(2, std2.id)
+ self.assertEqual('foo0', std2.foo)
+ self.assertEqual(0, std2.id)
def test_pk_force_value(self):
std1 = StandardFactory.create(id=10)
- self.assertEqual('foo1', std1.foo) # sequence was set before pk
+ self.assertEqual('foo1', std1.foo) # sequence and pk are unrelated
self.assertEqual(10, std1.id)
StandardFactory.reset_sequence()
std2 = StandardFactory.create()
- self.assertEqual('foo11', std2.foo)
- self.assertEqual(11, std2.id)
+ self.assertEqual('foo0', std2.foo) # Sequence doesn't care about pk
+ self.assertEqual(0, std2.id)
@unittest.skipIf(sqlalchemy is None, "SQLalchemy not installed.")
@@ -111,22 +111,22 @@ class SQLAlchemyNonIntegerPkTestCase(unittest.TestCase):
def test_first(self):
nonint = NonIntegerPkFactory.build()
- self.assertEqual('foo1', nonint.id)
+ self.assertEqual('foo0', nonint.id)
def test_many(self):
nonint1 = NonIntegerPkFactory.build()
nonint2 = NonIntegerPkFactory.build()
- self.assertEqual('foo1', nonint1.id)
- self.assertEqual('foo2', nonint2.id)
+ self.assertEqual('foo0', nonint1.id)
+ self.assertEqual('foo1', nonint2.id)
def test_creation(self):
nonint1 = NonIntegerPkFactory.create()
- self.assertEqual('foo1', nonint1.id)
+ self.assertEqual('foo0', nonint1.id)
NonIntegerPkFactory.reset_sequence()
nonint2 = NonIntegerPkFactory.build()
- self.assertEqual('foo1', nonint2.id)
+ self.assertEqual('foo0', nonint2.id)
def test_force_pk(self):
nonint1 = NonIntegerPkFactory.create(id='foo10')
@@ -134,4 +134,4 @@ class SQLAlchemyNonIntegerPkTestCase(unittest.TestCase):
NonIntegerPkFactory.reset_sequence()
nonint2 = NonIntegerPkFactory.create()
- self.assertEqual('foo1', nonint2.id)
+ self.assertEqual('foo0', nonint2.id)
diff --git a/tests/test_django.py b/tests/test_django.py
index 874c272..0cbef19 100644
--- a/tests/test_django.py
+++ b/tests/test_django.py
@@ -174,32 +174,32 @@ class DjangoPkSequenceTestCase(django_test.TestCase):
def test_pk_first(self):
std = StandardFactory.build()
- self.assertEqual('foo1', std.foo)
+ self.assertEqual('foo0', std.foo)
def test_pk_many(self):
std1 = StandardFactory.build()
std2 = StandardFactory.build()
- self.assertEqual('foo1', std1.foo)
- self.assertEqual('foo2', std2.foo)
+ self.assertEqual('foo0', std1.foo)
+ self.assertEqual('foo1', std2.foo)
def test_pk_creation(self):
std1 = StandardFactory.create()
- self.assertEqual('foo1', std1.foo)
+ self.assertEqual('foo0', std1.foo)
self.assertEqual(1, std1.pk)
StandardFactory.reset_sequence()
std2 = StandardFactory.create()
- self.assertEqual('foo2', std2.foo)
+ self.assertEqual('foo0', std2.foo)
self.assertEqual(2, std2.pk)
def test_pk_force_value(self):
std1 = StandardFactory.create(pk=10)
- self.assertEqual('foo1', std1.foo) # sequence was set before pk
+ self.assertEqual('foo0', std1.foo) # sequence is unrelated to pk
self.assertEqual(10, std1.pk)
StandardFactory.reset_sequence()
std2 = StandardFactory.create()
- self.assertEqual('foo11', std2.foo)
+ self.assertEqual('foo0', std2.foo)
self.assertEqual(11, std2.pk)
@@ -212,12 +212,12 @@ class DjangoPkForceTestCase(django_test.TestCase):
def test_no_pk(self):
std = StandardFactoryWithPKField()
self.assertIsNotNone(std.pk)
- self.assertEqual('foo1', std.foo)
+ self.assertEqual('foo0', std.foo)
def test_force_pk(self):
std = StandardFactoryWithPKField(pk=42)
self.assertIsNotNone(std.pk)
- self.assertEqual('foo1', std.foo)
+ self.assertEqual('foo0', std.foo)
def test_reuse_pk(self):
std1 = StandardFactoryWithPKField(foo='bar')
@@ -286,9 +286,9 @@ class DjangoModelLoadingTestCase(django_test.TestCase):
self.assertEqual(models.StandardModel, e1.__class__)
self.assertEqual(models.StandardSon, e2.__class__)
self.assertEqual(models.StandardModel, e3.__class__)
- self.assertEqual(1, e1.foo)
- self.assertEqual(2, e2.foo)
- self.assertEqual(3, e3.foo)
+ self.assertEqual(0, e1.foo)
+ self.assertEqual(1, e2.foo)
+ self.assertEqual(2, e3.foo)
@unittest.skipIf(django is None, "Django not installed.")
@@ -299,23 +299,23 @@ class DjangoNonIntegerPkTestCase(django_test.TestCase):
def test_first(self):
nonint = NonIntegerPkFactory.build()
- self.assertEqual('foo1', nonint.foo)
+ self.assertEqual('foo0', nonint.foo)
def test_many(self):
nonint1 = NonIntegerPkFactory.build()
nonint2 = NonIntegerPkFactory.build()
- self.assertEqual('foo1', nonint1.foo)
- self.assertEqual('foo2', nonint2.foo)
+ self.assertEqual('foo0', nonint1.foo)
+ self.assertEqual('foo1', nonint2.foo)
def test_creation(self):
nonint1 = NonIntegerPkFactory.create()
- self.assertEqual('foo1', nonint1.foo)
- self.assertEqual('foo1', nonint1.pk)
+ self.assertEqual('foo0', nonint1.foo)
+ self.assertEqual('foo0', nonint1.pk)
NonIntegerPkFactory.reset_sequence()
nonint2 = NonIntegerPkFactory.build()
- self.assertEqual('foo1', nonint2.foo)
+ self.assertEqual('foo0', nonint2.foo)
def test_force_pk(self):
nonint1 = NonIntegerPkFactory.create(pk='foo10')
@@ -324,8 +324,8 @@ class DjangoNonIntegerPkTestCase(django_test.TestCase):
NonIntegerPkFactory.reset_sequence()
nonint2 = NonIntegerPkFactory.create()
- self.assertEqual('foo1', nonint2.foo)
- self.assertEqual('foo1', nonint2.pk)
+ self.assertEqual('foo0', nonint2.foo)
+ self.assertEqual('foo0', nonint2.pk)
@unittest.skipIf(django is None, "Django not installed.")
diff --git a/tests/test_using.py b/tests/test_using.py
index 8d78789..8aba8b6 100644
--- a/tests/test_using.py
+++ b/tests/test_using.py
@@ -1490,12 +1490,6 @@ class BetterFakeModelManager(object):
instance.id = 2
return instance, True
- def values_list(self, *args, **kwargs):
- return self
-
- def order_by(self, *args, **kwargs):
- return [1]
-
class BetterFakeModel(object):
@classmethod
@@ -1618,14 +1612,14 @@ class DjangoModelFactoryTestCase(unittest.TestCase):
o1 = TestModelFactory()
o2 = TestModelFactory()
- self.assertEqual('foo_2', o1.a)
- self.assertEqual('foo_3', o2.a)
+ self.assertEqual('foo_0', o1.a)
+ self.assertEqual('foo_1', o2.a)
o3 = TestModelFactory.build()
o4 = TestModelFactory.build()
- self.assertEqual('foo_4', o3.a)
- self.assertEqual('foo_5', o4.a)
+ self.assertEqual('foo_2', o3.a)
+ self.assertEqual('foo_3', o4.a)
def test_no_get_or_create(self):
class TestModelFactory(factory.django.DjangoModelFactory):
@@ -1636,7 +1630,7 @@ class DjangoModelFactoryTestCase(unittest.TestCase):
o = TestModelFactory()
self.assertEqual(None, o._defaults)
- self.assertEqual('foo_2', o.a)
+ self.assertEqual('foo_0', o.a)
self.assertEqual(2, o.id)
def test_get_or_create(self):
@@ -1652,7 +1646,7 @@ class DjangoModelFactoryTestCase(unittest.TestCase):
o = TestModelFactory()
self.assertEqual({'c': 3, 'd': 4}, o._defaults)
- self.assertEqual('foo_2', o.a)
+ self.assertEqual('foo_0', o.a)
self.assertEqual(2, o.b)
self.assertEqual(3, o.c)
self.assertEqual(4, o.d)
@@ -1672,7 +1666,7 @@ class DjangoModelFactoryTestCase(unittest.TestCase):
o = TestModelFactory()
self.assertEqual({}, o._defaults)
- self.assertEqual('foo_2', o.a)
+ self.assertEqual('foo_0', o.a)
self.assertEqual(2, o.b)
self.assertEqual(3, o.c)
self.assertEqual(4, o.d)