From 00f5b75279436de20625d47a88a2e37850ff53fd Mon Sep 17 00:00:00 2001 From: Nikolay Kiryanov Date: Mon, 6 Oct 2025 11:13:24 +0300 Subject: [PATCH] Deps: replace mixer with faker + model_bakery --- {{ cookiecutter.name }}/pyproject.toml | 4 ++-- {{ cookiecutter.name }}/src/app/factory.py | 6 +---- .../src/app/testing/factory.py | 6 +++-- .../src/app/testing/mixer.py | 20 ---------------- .../src/app/testing/types.py | 6 +++-- {{ cookiecutter.name }}/src/users/factory.py | 2 +- {{ cookiecutter.name }}/uv.lock | 24 ++++++++++--------- 7 files changed, 25 insertions(+), 43 deletions(-) delete mode 100644 {{ cookiecutter.name }}/src/app/testing/mixer.py diff --git a/{{ cookiecutter.name }}/pyproject.toml b/{{ cookiecutter.name }}/pyproject.toml index 6bb43731..cfd2df5c 100644 --- a/{{ cookiecutter.name }}/pyproject.toml +++ b/{{ cookiecutter.name }}/pyproject.toml @@ -32,10 +32,11 @@ dev = [ "django-stubs>=5.2.0", "djangorestframework-stubs>=3.16.0", "dotenv-linter>=0.7.0", + "faker>=37.8.0", "freezegun>=1.5.1", "ipython>=9.2.0", "jedi>=0.19.2", - "mixer>=7.2.2", + "model-bakery>=1.20.5", "mypy>=1.15.0", "pymarkdownlnt>=0.9.29", "pytest-deadfixtures>=2.2.1", @@ -226,7 +227,6 @@ module = [ "djangorestframework_camel_case.*", "drf_orjson_renderer.*", "ipware.*", - "mixer.*", ] ignore_missing_imports = true diff --git a/{{ cookiecutter.name }}/src/app/factory.py b/{{ cookiecutter.name }}/src/app/factory.py index 431b008d..126415eb 100644 --- a/{{ cookiecutter.name }}/src/app/factory.py +++ b/{{ cookiecutter.name }}/src/app/factory.py @@ -1,13 +1,9 @@ from django.core.files.uploadedfile import SimpleUploadedFile -from faker import Faker from app.testing import register from app.testing.types import FactoryProtocol -faker = Faker() - - @register def image(self: FactoryProtocol, name: str = "image.gif", content_type: str = "image/gif") -> SimpleUploadedFile: - return SimpleUploadedFile(name=name, content=faker.image(), content_type=content_type) + return SimpleUploadedFile(name=name, content=self.faker.image(), content_type=content_type) diff --git a/{{ cookiecutter.name }}/src/app/testing/factory.py b/{{ cookiecutter.name }}/src/app/testing/factory.py index da4504de..cdcbabfb 100644 --- a/{{ cookiecutter.name }}/src/app/testing/factory.py +++ b/{{ cookiecutter.name }}/src/app/testing/factory.py @@ -1,7 +1,8 @@ from collections.abc import Callable from functools import partial -from app.testing.mixer import mixer +from faker import Faker +from model_bakery import baker def register(method: Callable) -> Callable: @@ -31,7 +32,8 @@ def __getattr__(self, name: str) -> Callable: class FixtureFactory: def __init__(self) -> None: - self.mixer = mixer + self.baker = baker # imported module + self.faker = Faker() self.registry = FixtureRegistry() def __getattr__(self, name: str) -> Callable: diff --git a/{{ cookiecutter.name }}/src/app/testing/mixer.py b/{{ cookiecutter.name }}/src/app/testing/mixer.py deleted file mode 100644 index f236533b..00000000 --- a/{{ cookiecutter.name }}/src/app/testing/mixer.py +++ /dev/null @@ -1,20 +0,0 @@ -import uuid - -from mixer.backend.django import mixer - - -__all__ = [ - "mixer", -] - - -def _random_user_name() -> str: - return str(uuid.uuid4()) - - -def _random_email() -> str: - uuid_as_str = str(uuid.uuid4()).replace("-", "_") - return f"{uuid_as_str}@mail.com" - - -mixer.register("users.User", username=_random_user_name, email=_random_email) diff --git a/{{ cookiecutter.name }}/src/app/testing/types.py b/{{ cookiecutter.name }}/src/app/testing/types.py index ca949a84..75e1be97 100644 --- a/{{ cookiecutter.name }}/src/app/testing/types.py +++ b/{{ cookiecutter.name }}/src/app/testing/types.py @@ -1,10 +1,12 @@ +from types import ModuleType from typing import Protocol -from mixer.backend.django import mixer +from faker import Faker class FactoryProtocol(Protocol): - mixer: mixer + baker: ModuleType + faker: Faker __all__ = [ diff --git a/{{ cookiecutter.name }}/src/users/factory.py b/{{ cookiecutter.name }}/src/users/factory.py index 57a1c786..5ef5ab95 100644 --- a/{{ cookiecutter.name }}/src/users/factory.py +++ b/{{ cookiecutter.name }}/src/users/factory.py @@ -7,7 +7,7 @@ @register def user(self: FactoryProtocol, **kwargs: dict) -> User: - return self.mixer.blend("users.User", **kwargs) + return self.baker.make("users.User", **kwargs) @register diff --git a/{{ cookiecutter.name }}/uv.lock b/{{ cookiecutter.name }}/uv.lock index 65bfcb73..cd52991e 100644 --- a/{{ cookiecutter.name }}/uv.lock +++ b/{{ cookiecutter.name }}/uv.lock @@ -561,14 +561,14 @@ wheels = [ [[package]] name = "faker" -version = "12.0.1" +version = "37.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-dateutil" }, + { name = "tzdata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/89/f2/ea1966e890603e172b7f3bebde614813a24986390799d4dd43960aeffd18/Faker-12.0.1.tar.gz", hash = "sha256:aa7103805ae793277abbb85da9f6f05e76a1a295a9384a8e17c2fba2b3a690cb", size = 1428846, upload-time = "2022-02-04T16:01:33.267Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/da/1336008d39e5d4076dddb4e0f3a52ada41429274bf558a3cc28030d324a3/faker-37.8.0.tar.gz", hash = "sha256:090bb5abbec2b30949a95ce1ba6b20d1d0ed222883d63483a0d4be4a970d6fb8", size = 1912113, upload-time = "2025-09-15T20:24:13.592Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/10/9a650725c310f61160909637446c18b92db7585ddf3326bc0767b850075e/Faker-12.0.1-py3-none-any.whl", hash = "sha256:1dc2811f20e163892fefe7006f2ce00778f8099a40aee265bfa60a13400de63d", size = 1464239, upload-time = "2022-02-04T16:01:30.623Z" }, + { url = "https://files.pythonhosted.org/packages/f5/11/02ebebb09ff2104b690457cb7bc6ed700c9e0ce88cf581486bb0a5d3c88b/faker-37.8.0-py3-none-any.whl", hash = "sha256:b08233118824423b5fc239f7dd51f145e7018082b4164f8da6a9994e1f1ae793", size = 1953940, upload-time = "2025-09-15T20:24:11.482Z" }, ] [[package]] @@ -718,15 +718,15 @@ wheels = [ ] [[package]] -name = "mixer" -version = "7.2.2" +name = "model-bakery" +version = "1.20.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "faker" }, + { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dd/7b/95e5ee5d6e5d9764b57bb0ec7aa823896740954c5a048568780943052770/mixer-7.2.2.tar.gz", hash = "sha256:9b3f1a261b56d8f2394f39955f83adbc7ff3ab4bb1065ebfec19a10d3e8501e0", size = 49639, upload-time = "2022-03-23T14:39:33.528Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/73/24854c5053c852201b4799e7837060496d1418a28488a90a299e8d9c618b/model_bakery-1.20.5.tar.gz", hash = "sha256:107b3efb8889baac83cae0e2d81465903b69a70eeb99ecfd0929d959a653ab90", size = 21332, upload-time = "2025-06-07T10:21:47.727Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/73/60ab9b2a61a98f84f71f567a835dc877a9608fcff617e047ff96687c3796/mixer-7.2.2-py3-none-any.whl", hash = "sha256:8089b8e2d00288c77e622936198f5dd03c8ac1603a1530a4f870dc213363b2ae", size = 38481, upload-time = "2022-03-23T14:39:31.52Z" }, + { url = "https://files.pythonhosted.org/packages/13/4b/157c1113e317f79a257b4dfe0607dbab7f57bec67a34d053588dfb8945ac/model_bakery-1.20.5-py3-none-any.whl", hash = "sha256:796e0b7fa6bf2acc09feaadce40c6bcc13e5b55c5bdff9f76e87ceb64f736070", size = 24292, upload-time = "2025-06-07T10:21:46.438Z" }, ] [[package]] @@ -1245,10 +1245,11 @@ dev = [ { name = "django-stubs" }, { name = "djangorestframework-stubs" }, { name = "dotenv-linter" }, + { name = "faker" }, { name = "freezegun" }, { name = "ipython" }, { name = "jedi" }, - { name = "mixer" }, + { name = "model-bakery" }, { name = "mypy" }, { name = "pymarkdownlnt" }, { name = "pytest-deadfixtures" }, @@ -1293,10 +1294,11 @@ dev = [ { name = "django-stubs", specifier = ">=5.2.0" }, { name = "djangorestframework-stubs", specifier = ">=3.16.0" }, { name = "dotenv-linter", specifier = ">=0.7.0" }, + { name = "faker", specifier = ">=37.8.0" }, { name = "freezegun", specifier = ">=1.5.1" }, { name = "ipython", specifier = ">=9.2.0" }, { name = "jedi", specifier = ">=0.19.2" }, - { name = "mixer", specifier = ">=7.2.2" }, + { name = "model-bakery", specifier = ">=1.20.5" }, { name = "mypy", specifier = ">=1.15.0" }, { name = "pymarkdownlnt", specifier = ">=0.9.29" }, { name = "pytest-deadfixtures", specifier = ">=2.2.1" },