Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated features #1091

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ ChangeLog

.. Note for v4.x: don't forget to check "Deprecated" sections for removal.

3.3.2 (unreleased)
4.0.0 (unreleased)
------------------

- Nothing changed yet.
*Removed:*

- :class:`~factory.django.DjangoModelFactory` no longer issues a second call to
:meth:`~django.db.models.Model.save` on the created instance when :ref:`post-generation-hooks` return a value.

The transitional setting :attr:`factory.django.DjangoOptions.skip_postgeneration_save` can be removed.

- :func:`factory.use_strategy`. Use :attr:`factory.FactoryOptions.strategy` instead.

3.3.1 (2024-08-18)
------------------
Expand Down
7 changes: 0 additions & 7 deletions docs/orms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,6 @@ All factories for a Django :class:`~django.db.models.Model` should use the
>>> john.email # The email value was not updated
"[email protected]"

.. attribute:: skip_postgeneration_save

Transitional option to prevent :class:`~factory.django.DjangoModelFactory`'s
``_after_postgeneration`` from issuing a duplicate call to
:meth:`~django.db.models.Model.save` on the created instance when
:class:`factory.PostGeneration` hooks return a value.


Extra fields
""""""""""""
Expand Down
17 changes: 0 additions & 17 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -579,23 +579,6 @@ factory_boy supports two main strategies for generating instances, plus stubs.
>>> return obj


.. function:: use_strategy(strategy)

.. deprecated:: 3.2

Use :py:attr:`factory.FactoryOptions.strategy` instead.

*Decorator*

Change the default strategy of the decorated :class:`Factory` to the chosen ``strategy``:

.. code-block:: python

@use_strategy(factory.BUILD_STRATEGY)
class UserBuildingFactory(UserFactory):
pass


.. data:: STUB_STRATEGY

The 'stub' strategy is an exception in the factory_boy world: it doesn't return
Expand Down
1 change: 0 additions & 1 deletion factory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
Factory,
ListFactory,
StubFactory,
use_strategy,
)
from .declarations import (
ContainerAttribute,
Expand Down
17 changes: 0 additions & 17 deletions factory/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,20 +727,3 @@ def _create(cls, model_class, *args, **kwargs):
class ListFactory(BaseListFactory):
class Meta:
model = list


def use_strategy(new_strategy):
"""Force the use of a different strategy.

This is an alternative to setting default_strategy in the class definition.
"""
warnings.warn(
"use_strategy() is deprecated and will be removed in the future.",
DeprecationWarning,
stacklevel=2,
)

def wrapped_class(klass):
klass._meta.strategy = new_strategy
return klass
return wrapped_class
19 changes: 0 additions & 19 deletions factory/django.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import io
import logging
import os
import warnings
from typing import Dict, TypeVar

from django.contrib.auth.hashers import make_password
Expand Down Expand Up @@ -50,7 +49,6 @@ def _build_default_options(self):
return super()._build_default_options() + [
base.OptionDefault('django_get_or_create', (), inherit=True),
base.OptionDefault('database', DEFAULT_DB_ALIAS, inherit=True),
base.OptionDefault('skip_postgeneration_save', False, inherit=True),
]

def _get_counter_reference(self):
Expand Down Expand Up @@ -174,23 +172,6 @@ def _create(cls, model_class, *args, **kwargs):
manager = cls._get_manager(model_class)
return manager.create(*args, **kwargs)

# DEPRECATED. Remove this override with the next major release.
@classmethod
def _after_postgeneration(cls, instance, create, results=None):
"""Save again the instance if creating and at least one hook ran."""
if create and results and not cls._meta.skip_postgeneration_save:
warnings.warn(
f"{cls.__name__}._after_postgeneration will stop saving the instance "
"after postgeneration hooks in the next major release.\n"
"If the save call is extraneous, set skip_postgeneration_save=True "
f"in the {cls.__name__}.Meta.\n"
"To keep saving the instance, move the save call to your "
"postgeneration hooks or override _after_postgeneration.",
DeprecationWarning,
)
# Some post-generation hooks ran, and may have modified us.
instance.save()


class Password(declarations.Transformer):
def __init__(self, password, transform=make_password, **kwargs):
Expand Down
34 changes: 0 additions & 34 deletions tests/test_django.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,9 +447,6 @@ class PointedRelatedFactory(PointedFactory):
factory_related_name='pointed',
)

class Meta:
skip_postgeneration_save = True

class PointerExtraFactory(PointerFactory):
pointed__foo = 'extra_new_foo'

Expand All @@ -466,9 +463,6 @@ class Params:
)
)

class Meta:
skip_postgeneration_save = True

cls.PointedFactory = PointedFactory
cls.PointerFactory = PointerFactory
cls.PointedRelatedFactory = PointedRelatedFactory
Expand Down Expand Up @@ -989,7 +983,6 @@ def test_class_decorator_with_subfactory(self):
class WithSignalsDecoratedFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.WithSignals
skip_postgeneration_save = True

@factory.post_generation
def post(obj, create, extracted, **kwargs):
Expand Down Expand Up @@ -1017,7 +1010,6 @@ def test_class_decorator_related_model_with_post_hook(self):
class PointedFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.PointedModel
skip_postgeneration_save = True

@factory.post_generation
def post_action(obj, create, extracted, **kwargs):
Expand Down Expand Up @@ -1111,7 +1103,6 @@ def test_class_decorator_with_muted_related_factory(self):
class UndecoratedFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.PointerModel
skip_postgeneration_save = True
pointed = factory.RelatedFactory(self.WithSignalsDecoratedFactory)

UndecoratedFactory()
Expand All @@ -1134,31 +1125,6 @@ class Meta:
ObjFactory.create(arg='invalid')


class DjangoModelFactoryDuplicateSaveDeprecationTest(django_test.TestCase):
class StandardFactoryWithPost(StandardFactory):
@factory.post_generation
def post_action(obj, create, extracted, **kwargs):
return 3

def test_create_warning(self):
with self.assertWarns(DeprecationWarning) as cm:
self.StandardFactoryWithPost.create()

[msg] = cm.warning.args
self.assertEqual(
msg,
"StandardFactoryWithPost._after_postgeneration will stop saving the "
"instance after postgeneration hooks in the next major release.\n"
"If the save call is extraneous, set skip_postgeneration_save=True in the "
"StandardFactoryWithPost.Meta.\n"
"To keep saving the instance, move the save call to your postgeneration "
"hooks or override _after_postgeneration.",
)

def test_build_no_warning(self):
self.StandardFactoryWithPost.build()


class IntegrityErrorForMissingOriginalParamsTest(django_test.TestCase):

def test_raises_integrity_error(self):
Expand Down
Loading