model_mommy-1.2/0000755000175000017500000000000012237016123015707 5ustar vandersonvanderson00000000000000model_mommy-1.2/MANIFEST.in0000644000175000017500000000016012163352632017450 0ustar vandersonvanderson00000000000000include model_mommy/mock_file.txt include model_mommy/mock-img.jpeg include README.rst include requirements.txt model_mommy-1.2/setup.cfg0000644000175000017500000000007312237016123017530 0ustar vandersonvanderson00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 model_mommy-1.2/setup.py0000644000175000017500000000200412237010141017407 0ustar vandersonvanderson00000000000000import setuptools from os.path import join, dirname import model_mommy setuptools.setup( name="model_mommy", version=model_mommy.__version__, packages=["model_mommy"], include_package_data=True, # declarations in MANIFEST.in install_requires=open(join(dirname(__file__), 'requirements.txt')).readlines(), tests_require=[ 'django<1.7', 'pil', 'tox', ], test_suite='runtests.runtests', author="vandersonmota", author_email="vandersonmota@gmail.com", url="http://github.com/vandersonmota/model_mommy", license="Apache 2.0", description="Smart object creation facility for Django.", long_description=open(join(dirname(__file__), "README.rst")).read(), keywords="django testing factory python", classifiers=[ 'Framework :: Django', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent', 'Topic :: Software Development', ], ) model_mommy-1.2/model_mommy.egg-info/0000755000175000017500000000000012237016123021717 5ustar vandersonvanderson00000000000000model_mommy-1.2/model_mommy.egg-info/requires.txt0000644000175000017500000000004112237016121024310 0ustar vandersonvanderson00000000000000Django<1.7 mock==1.0.1 six==1.3.0model_mommy-1.2/model_mommy.egg-info/SOURCES.txt0000644000175000017500000000064112237016123023604 0ustar vandersonvanderson00000000000000MANIFEST.in README.rst requirements.txt setup.py model_mommy/__init__.py model_mommy/exceptions.py model_mommy/generators.py model_mommy/mock-img.jpeg model_mommy/mock_file.txt model_mommy/mommy.py model_mommy/recipe.py model_mommy/timezone.py model_mommy.egg-info/PKG-INFO model_mommy.egg-info/SOURCES.txt model_mommy.egg-info/dependency_links.txt model_mommy.egg-info/requires.txt model_mommy.egg-info/top_level.txtmodel_mommy-1.2/model_mommy.egg-info/PKG-INFO0000644000175000017500000003570312237016121023022 0ustar vandersonvanderson00000000000000Metadata-Version: 1.1 Name: model-mommy Version: 1.2 Summary: Smart object creation facility for Django. Home-page: http://github.com/vandersonmota/model_mommy Author: vandersonmota Author-email: vandersonmota@gmail.com License: Apache 2.0 Description: ============================================ Model Mommy: Smart fixtures for better tests ============================================ *Model-mommy* offers you a smart way to create fixtures for testing in Django. With a simple and powerful API you can create many objects with a single line of code. .. image:: https://travis-ci.org/vandersonmota/model_mommy.png?branch=master :target: https://travis-ci.org/vandersonmota/model_mommy Install ======= .. code-block:: console pip install model_mommy Basic usage =========== Let's say you have an app **family** with a model like this: .. code-block:: python class Kid(models.Model): happy = models.BooleanField() name = models.CharField(max_length=30) age = models.IntegerField() bio = models.TextField() wanted_games_qtd = models.BigIntegerField() birthday = models.DateField() appointment = models.DateTimeField() To create a persisted instance, just call *Mommy*: .. code-block:: python from model_mommy import mommy from family.models import Kid kid = mommy.make(Kid) No need to pass attributes every damn time. Importing every model over and over again is boring. So let *Mommy* import them for you: .. code-block:: python from model_mommy import mommy # 1st form: app_label.model_name kid = mommy.make('family.Kid') # 2nd form: model_name dog = mommy.make('Dog') .. [1] You can only use the 2nd form on unique model names. If you have an app *family* with a *Dog*, and an app *farm* with a *Dog*, you must use the `app_label.model_name` form. .. [2] `model_name` is case insensitive. Model Relationships ------------------- *Mommy* also handles relationships. Say the kid has a dog: .. code-block:: python class Dog(models.Model): owner = models.ForeignKey('Kid') when you ask *Mommy*: .. code-block:: python from model_mommy import mommy rex = mommy.make('family.Dog') She will also create the `Kid`, automagically. Defining some attributes ------------------------ Of course it's possible to explicitly set values for attributes. .. code-block:: python from model_mommy import mommy another_kid = mommy.make('family.Kid', age=3) Related objects attributes are also reachable: .. code-block:: python from model_mommy import mommy bobs_dog = mommy.make('family.Dog', owner__name='Bob') Non persistent objects ---------------------- If don't need a persisted object, *Mommy* can handle this for you as well: .. code-block:: python from model_mommy import mommy kid = mommy.prepare('family.Kid') It works like `make`, but it doesn't persist the instance. More than one instance ---------------------- If you need to create more than one instance of the model, you can use the `_quantity` parameter for it: .. code-block:: python from model_mommy import mommy kids = mommy.make('family.Kid', _quantity=3) assert len(kids) == 3 It also works with `prepare`: .. code-block:: python from model_mommy import mommy kids = mommy.prepare('family.Kid', _quantity=3) assert len(kids) == 3 How mommy behaves? ================== By default, *model-mommy* skips fields with `null=True` or `blank=True`. Also if a field has a *default* value, it will be used. You can override this behavior by explicitly defining values. When shouldn't you let mommy generate things for you? ----------------------------------------------------- If you have fields with special validation, you should set their values by yourself. *Model-mommy* should handle fields that: 1. don't matter for the test you're writing; 2. don't require special validation (like unique, etc); 3. are required to create the object. Currently supported fields -------------------------- * BooleanField, IntegerField, BigIntegerField, SmallIntegerField, PositiveIntegerField, PositiveSmallIntegerField, FloatField, DecimalField * CharField, TextField, SlugField, URLField, EmailField * ForeignKey, OneToOneField, ManyToManyField (even with through model) * DateField, DateTimeField, TimeField * FileField, ImageField Custom fields ------------- Model-mommy allows you to define generators methods for your custom fields or overrides its default generators. This could be achieved by specifing a dict on settings that its keys are the field paths and the values their generators functions, as the example bellow: .. code-block:: python # on your settings.py file: def gen_func(): return 'value' MOMMY_CUSTOM_FIELDS_GEN = { 'test.generic.fields.CustomField': gen_func, } Recipes ======= If you're not confortable with random data or even you just want to improve the semantics of the generated data, there's hope for you. You can define a **recipe**, which is a set of rules to generate data for your models. Create a module called `mommy_recipes.py` at your app's root directory: .. code-block:: python from model_mommy.recipe import Recipe from family.models import Person person = Recipe(Person, name = 'John Doe', nickname = 'joe', age = 18, birthday = date.today(), appointment = datetime.now() ) Note you don't have to declare all the fields if you don't want to. Omitted fields will be generated automatically. The variable `person` serves as the recipe name: .. code-block:: python from model_mommy import mommy mommy.make_recipe('family.person') Or if you don't want a persisted instance: .. code-block:: python from model_mommy import mommy mommy.prepare_recipe('family.person') You can use the `_quantity` parameter as well if you want to create more than one object from a single recipe. You can define recipes locally to your module or test case as well. This can be useful for cases where a particular set of values may be unique to a particular test case, but used repeatedly there. .. code-block:: python company_recipe = Recipe(Company, name='WidgetCo') class EmployeeTest(TestCase): def setUp(self): self.employee_recipe = Recipe( Employee, name=seq('Employee '), company=company_recipe.make()) def test_employee_list(self): self.employee_recipe.make(_quantity=3) # test stuff.... def test_employee_tasks(self): employee1 = self.employee_recipe.make() task_recipe = Recipe(Task, employee=employee1) task_recipe.make(status='done') task_recipe.make(due_date=datetime(2014, 1, 1)) # test stuff.... Recipes with foreign keys ------------------------- You can define `foreign_key` relations: .. code-block:: python from model_mommy.recipe import Recipe, foreign_key from family.models import Person, Dog person = Recipe(Person, name = 'John Doe', nickname = 'joe', age = 18, birthday = date.today(), appointment = datetime.now() ) dog = Recipe(Dog, breed = 'Pug', owner = foreign_key(person) ) Notice that `person` is a *recipe*. You may be thinking: "I can put the Person model instance directly in the owner field". That's not recommended. Using the `foreign_key` is important for 2 reasons: * Semantics. You'll know that attribute is a foreign key when you're reading; * The associated instance will be created only when you call `make_recipe` and not during recipe definition; Recipes with callables ---------------------- It's possible to use *callables* as recipe's attribute value. .. code-block:: python from datetime import date from model_mommy.recipe import Recipe from family.models import Person person = Recipe(Person, birthday = date.today, ) When you call `make_recipe`, *Mommy* will set the attribute to the value returned by the callable. Sequences in recipes ---------------------- Sometimes, you have a field with an unique value and using `make` can cause random errors. Also, passing an attribute value just to avoid uniqueness validation problems can be tedious. To solve this you can define a sequence with `seq` .. code-block:: python from model_mommy.recipe import Recipe, seq from family.models import Person person = Recipe(Person, name = seq('Joe'), age = seq(15) ) p = mommy.make_recipe('myapp.person') p.name >>> 'Joe1' p.age >>> 16 p = mommy.make_recipe('myapp.person') p.name >>> 'Joe2' p.age >>> 17 This will append a counter to strings to avoid uniqueness problems and it will sum the counter with numerical values. You can also provide an optional `increment_by` argument which will modify incrementing behaviour. This can be an integer, float or Decimal. .. code-block:: python person = Recipe(Person, age = seq(15, increment_by=3) height_ft = seq(5.5, increment_by=.25) ) p = mommy.make_recipe('myapp.person') p.age >>> 18 p.height_ft >>> 5.75 p = mommy.make_recipe('myapp.person') p.age >>> 21 p.height_ft >>> 6.0 Overriding recipe definitions ----------------------------- Passing values when calling `make_recipe` or `prepare_recipe` will override the recipe rule. .. code-block:: python from model_mommy import mommy mommy.make_recipe('model_mommy.person', name='Peter Parker') This is useful when you have to create multiple objects and you have some unique field, for instance. Deprecation Warnings ==================== Because of the changes of model_mommy's API, the following methods are deprecated and will be removed in one of the future releases: * `mommy.make_one` -> should use the method `mommy.make` instead * `mommy.prepare_one` -> should use the method `mommy.prepare` instead * `mommy.make_many` -> should use the method `mommy.make` with the `_quantity` parameter instead * `mommy.make_many_from_recipe` -> should use the method `mommy.make_recipe` with the `_quantity` parameter instead Known Issues ============ django-taggit ------------- Model-mommy identifies django-taggit's `TaggableManager` as a normal Django field, which can lead to errors: .. code-block:: pycon TypeError: is not supported by mommy. The fix for this is to set ``blank=True`` on your ``TaggableManager``. Extensions ========== GeoDjango --------- Works with it? This project has some custom generators for it: https://github.com/sigma-consultoria/mommy_spatial_generators Contributing ============ 1. Prepare a virtual environment. .. code-block:: console pip install virtualenvwrapper mkvirtualenv --no-site-packages --distribute 2. Install the requirements. .. code-block:: console pip install -r requirements.txt 3. Run the tests. .. code-block:: console make test Inspiration =========== *Model-mommy* was inspired by many great open source software like ruby's ObjectDaddy and FactoryGirl. Doubts? Loved it? Hated it? Suggestions? ======================================== Join our mailing list for support, development and ideas! * https://groups.google.com/group/model-mommy Keywords: django testing factory python Platform: UNKNOWN Classifier: Framework :: Django Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Topic :: Software Development model_mommy-1.2/model_mommy.egg-info/dependency_links.txt0000644000175000017500000000000112237016121025763 0ustar vandersonvanderson00000000000000 model_mommy-1.2/model_mommy.egg-info/top_level.txt0000644000175000017500000000001412237016121024442 0ustar vandersonvanderson00000000000000model_mommy model_mommy-1.2/README.rst0000644000175000017500000002600712235440324017405 0ustar vandersonvanderson00000000000000============================================ Model Mommy: Smart fixtures for better tests ============================================ *Model-mommy* offers you a smart way to create fixtures for testing in Django. With a simple and powerful API you can create many objects with a single line of code. .. image:: https://travis-ci.org/vandersonmota/model_mommy.png?branch=master :target: https://travis-ci.org/vandersonmota/model_mommy Install ======= .. code-block:: console pip install model_mommy Basic usage =========== Let's say you have an app **family** with a model like this: .. code-block:: python class Kid(models.Model): happy = models.BooleanField() name = models.CharField(max_length=30) age = models.IntegerField() bio = models.TextField() wanted_games_qtd = models.BigIntegerField() birthday = models.DateField() appointment = models.DateTimeField() To create a persisted instance, just call *Mommy*: .. code-block:: python from model_mommy import mommy from family.models import Kid kid = mommy.make(Kid) No need to pass attributes every damn time. Importing every model over and over again is boring. So let *Mommy* import them for you: .. code-block:: python from model_mommy import mommy # 1st form: app_label.model_name kid = mommy.make('family.Kid') # 2nd form: model_name dog = mommy.make('Dog') .. [1] You can only use the 2nd form on unique model names. If you have an app *family* with a *Dog*, and an app *farm* with a *Dog*, you must use the `app_label.model_name` form. .. [2] `model_name` is case insensitive. Model Relationships ------------------- *Mommy* also handles relationships. Say the kid has a dog: .. code-block:: python class Dog(models.Model): owner = models.ForeignKey('Kid') when you ask *Mommy*: .. code-block:: python from model_mommy import mommy rex = mommy.make('family.Dog') She will also create the `Kid`, automagically. Defining some attributes ------------------------ Of course it's possible to explicitly set values for attributes. .. code-block:: python from model_mommy import mommy another_kid = mommy.make('family.Kid', age=3) Related objects attributes are also reachable: .. code-block:: python from model_mommy import mommy bobs_dog = mommy.make('family.Dog', owner__name='Bob') Non persistent objects ---------------------- If don't need a persisted object, *Mommy* can handle this for you as well: .. code-block:: python from model_mommy import mommy kid = mommy.prepare('family.Kid') It works like `make`, but it doesn't persist the instance. More than one instance ---------------------- If you need to create more than one instance of the model, you can use the `_quantity` parameter for it: .. code-block:: python from model_mommy import mommy kids = mommy.make('family.Kid', _quantity=3) assert len(kids) == 3 It also works with `prepare`: .. code-block:: python from model_mommy import mommy kids = mommy.prepare('family.Kid', _quantity=3) assert len(kids) == 3 How mommy behaves? ================== By default, *model-mommy* skips fields with `null=True` or `blank=True`. Also if a field has a *default* value, it will be used. You can override this behavior by explicitly defining values. When shouldn't you let mommy generate things for you? ----------------------------------------------------- If you have fields with special validation, you should set their values by yourself. *Model-mommy* should handle fields that: 1. don't matter for the test you're writing; 2. don't require special validation (like unique, etc); 3. are required to create the object. Currently supported fields -------------------------- * BooleanField, IntegerField, BigIntegerField, SmallIntegerField, PositiveIntegerField, PositiveSmallIntegerField, FloatField, DecimalField * CharField, TextField, SlugField, URLField, EmailField * ForeignKey, OneToOneField, ManyToManyField (even with through model) * DateField, DateTimeField, TimeField * FileField, ImageField Custom fields ------------- Model-mommy allows you to define generators methods for your custom fields or overrides its default generators. This could be achieved by specifing a dict on settings that its keys are the field paths and the values their generators functions, as the example bellow: .. code-block:: python # on your settings.py file: def gen_func(): return 'value' MOMMY_CUSTOM_FIELDS_GEN = { 'test.generic.fields.CustomField': gen_func, } Recipes ======= If you're not confortable with random data or even you just want to improve the semantics of the generated data, there's hope for you. You can define a **recipe**, which is a set of rules to generate data for your models. Create a module called `mommy_recipes.py` at your app's root directory: .. code-block:: python from model_mommy.recipe import Recipe from family.models import Person person = Recipe(Person, name = 'John Doe', nickname = 'joe', age = 18, birthday = date.today(), appointment = datetime.now() ) Note you don't have to declare all the fields if you don't want to. Omitted fields will be generated automatically. The variable `person` serves as the recipe name: .. code-block:: python from model_mommy import mommy mommy.make_recipe('family.person') Or if you don't want a persisted instance: .. code-block:: python from model_mommy import mommy mommy.prepare_recipe('family.person') You can use the `_quantity` parameter as well if you want to create more than one object from a single recipe. You can define recipes locally to your module or test case as well. This can be useful for cases where a particular set of values may be unique to a particular test case, but used repeatedly there. .. code-block:: python company_recipe = Recipe(Company, name='WidgetCo') class EmployeeTest(TestCase): def setUp(self): self.employee_recipe = Recipe( Employee, name=seq('Employee '), company=company_recipe.make()) def test_employee_list(self): self.employee_recipe.make(_quantity=3) # test stuff.... def test_employee_tasks(self): employee1 = self.employee_recipe.make() task_recipe = Recipe(Task, employee=employee1) task_recipe.make(status='done') task_recipe.make(due_date=datetime(2014, 1, 1)) # test stuff.... Recipes with foreign keys ------------------------- You can define `foreign_key` relations: .. code-block:: python from model_mommy.recipe import Recipe, foreign_key from family.models import Person, Dog person = Recipe(Person, name = 'John Doe', nickname = 'joe', age = 18, birthday = date.today(), appointment = datetime.now() ) dog = Recipe(Dog, breed = 'Pug', owner = foreign_key(person) ) Notice that `person` is a *recipe*. You may be thinking: "I can put the Person model instance directly in the owner field". That's not recommended. Using the `foreign_key` is important for 2 reasons: * Semantics. You'll know that attribute is a foreign key when you're reading; * The associated instance will be created only when you call `make_recipe` and not during recipe definition; Recipes with callables ---------------------- It's possible to use *callables* as recipe's attribute value. .. code-block:: python from datetime import date from model_mommy.recipe import Recipe from family.models import Person person = Recipe(Person, birthday = date.today, ) When you call `make_recipe`, *Mommy* will set the attribute to the value returned by the callable. Sequences in recipes ---------------------- Sometimes, you have a field with an unique value and using `make` can cause random errors. Also, passing an attribute value just to avoid uniqueness validation problems can be tedious. To solve this you can define a sequence with `seq` .. code-block:: python from model_mommy.recipe import Recipe, seq from family.models import Person person = Recipe(Person, name = seq('Joe'), age = seq(15) ) p = mommy.make_recipe('myapp.person') p.name >>> 'Joe1' p.age >>> 16 p = mommy.make_recipe('myapp.person') p.name >>> 'Joe2' p.age >>> 17 This will append a counter to strings to avoid uniqueness problems and it will sum the counter with numerical values. You can also provide an optional `increment_by` argument which will modify incrementing behaviour. This can be an integer, float or Decimal. .. code-block:: python person = Recipe(Person, age = seq(15, increment_by=3) height_ft = seq(5.5, increment_by=.25) ) p = mommy.make_recipe('myapp.person') p.age >>> 18 p.height_ft >>> 5.75 p = mommy.make_recipe('myapp.person') p.age >>> 21 p.height_ft >>> 6.0 Overriding recipe definitions ----------------------------- Passing values when calling `make_recipe` or `prepare_recipe` will override the recipe rule. .. code-block:: python from model_mommy import mommy mommy.make_recipe('model_mommy.person', name='Peter Parker') This is useful when you have to create multiple objects and you have some unique field, for instance. Deprecation Warnings ==================== Because of the changes of model_mommy's API, the following methods are deprecated and will be removed in one of the future releases: * `mommy.make_one` -> should use the method `mommy.make` instead * `mommy.prepare_one` -> should use the method `mommy.prepare` instead * `mommy.make_many` -> should use the method `mommy.make` with the `_quantity` parameter instead * `mommy.make_many_from_recipe` -> should use the method `mommy.make_recipe` with the `_quantity` parameter instead Known Issues ============ django-taggit ------------- Model-mommy identifies django-taggit's `TaggableManager` as a normal Django field, which can lead to errors: .. code-block:: pycon TypeError: is not supported by mommy. The fix for this is to set ``blank=True`` on your ``TaggableManager``. Extensions ========== GeoDjango --------- Works with it? This project has some custom generators for it: https://github.com/sigma-consultoria/mommy_spatial_generators Contributing ============ 1. Prepare a virtual environment. .. code-block:: console pip install virtualenvwrapper mkvirtualenv --no-site-packages --distribute 2. Install the requirements. .. code-block:: console pip install -r requirements.txt 3. Run the tests. .. code-block:: console make test Inspiration =========== *Model-mommy* was inspired by many great open source software like ruby's ObjectDaddy and FactoryGirl. Doubts? Loved it? Hated it? Suggestions? ======================================== Join our mailing list for support, development and ideas! * https://groups.google.com/group/model-mommy model_mommy-1.2/requirements.txt0000644000175000017500000000004212237010153021164 0ustar vandersonvanderson00000000000000Django<1.7 mock==1.0.1 six==1.3.0 model_mommy-1.2/PKG-INFO0000644000175000017500000003570312237016123017014 0ustar vandersonvanderson00000000000000Metadata-Version: 1.1 Name: model_mommy Version: 1.2 Summary: Smart object creation facility for Django. Home-page: http://github.com/vandersonmota/model_mommy Author: vandersonmota Author-email: vandersonmota@gmail.com License: Apache 2.0 Description: ============================================ Model Mommy: Smart fixtures for better tests ============================================ *Model-mommy* offers you a smart way to create fixtures for testing in Django. With a simple and powerful API you can create many objects with a single line of code. .. image:: https://travis-ci.org/vandersonmota/model_mommy.png?branch=master :target: https://travis-ci.org/vandersonmota/model_mommy Install ======= .. code-block:: console pip install model_mommy Basic usage =========== Let's say you have an app **family** with a model like this: .. code-block:: python class Kid(models.Model): happy = models.BooleanField() name = models.CharField(max_length=30) age = models.IntegerField() bio = models.TextField() wanted_games_qtd = models.BigIntegerField() birthday = models.DateField() appointment = models.DateTimeField() To create a persisted instance, just call *Mommy*: .. code-block:: python from model_mommy import mommy from family.models import Kid kid = mommy.make(Kid) No need to pass attributes every damn time. Importing every model over and over again is boring. So let *Mommy* import them for you: .. code-block:: python from model_mommy import mommy # 1st form: app_label.model_name kid = mommy.make('family.Kid') # 2nd form: model_name dog = mommy.make('Dog') .. [1] You can only use the 2nd form on unique model names. If you have an app *family* with a *Dog*, and an app *farm* with a *Dog*, you must use the `app_label.model_name` form. .. [2] `model_name` is case insensitive. Model Relationships ------------------- *Mommy* also handles relationships. Say the kid has a dog: .. code-block:: python class Dog(models.Model): owner = models.ForeignKey('Kid') when you ask *Mommy*: .. code-block:: python from model_mommy import mommy rex = mommy.make('family.Dog') She will also create the `Kid`, automagically. Defining some attributes ------------------------ Of course it's possible to explicitly set values for attributes. .. code-block:: python from model_mommy import mommy another_kid = mommy.make('family.Kid', age=3) Related objects attributes are also reachable: .. code-block:: python from model_mommy import mommy bobs_dog = mommy.make('family.Dog', owner__name='Bob') Non persistent objects ---------------------- If don't need a persisted object, *Mommy* can handle this for you as well: .. code-block:: python from model_mommy import mommy kid = mommy.prepare('family.Kid') It works like `make`, but it doesn't persist the instance. More than one instance ---------------------- If you need to create more than one instance of the model, you can use the `_quantity` parameter for it: .. code-block:: python from model_mommy import mommy kids = mommy.make('family.Kid', _quantity=3) assert len(kids) == 3 It also works with `prepare`: .. code-block:: python from model_mommy import mommy kids = mommy.prepare('family.Kid', _quantity=3) assert len(kids) == 3 How mommy behaves? ================== By default, *model-mommy* skips fields with `null=True` or `blank=True`. Also if a field has a *default* value, it will be used. You can override this behavior by explicitly defining values. When shouldn't you let mommy generate things for you? ----------------------------------------------------- If you have fields with special validation, you should set their values by yourself. *Model-mommy* should handle fields that: 1. don't matter for the test you're writing; 2. don't require special validation (like unique, etc); 3. are required to create the object. Currently supported fields -------------------------- * BooleanField, IntegerField, BigIntegerField, SmallIntegerField, PositiveIntegerField, PositiveSmallIntegerField, FloatField, DecimalField * CharField, TextField, SlugField, URLField, EmailField * ForeignKey, OneToOneField, ManyToManyField (even with through model) * DateField, DateTimeField, TimeField * FileField, ImageField Custom fields ------------- Model-mommy allows you to define generators methods for your custom fields or overrides its default generators. This could be achieved by specifing a dict on settings that its keys are the field paths and the values their generators functions, as the example bellow: .. code-block:: python # on your settings.py file: def gen_func(): return 'value' MOMMY_CUSTOM_FIELDS_GEN = { 'test.generic.fields.CustomField': gen_func, } Recipes ======= If you're not confortable with random data or even you just want to improve the semantics of the generated data, there's hope for you. You can define a **recipe**, which is a set of rules to generate data for your models. Create a module called `mommy_recipes.py` at your app's root directory: .. code-block:: python from model_mommy.recipe import Recipe from family.models import Person person = Recipe(Person, name = 'John Doe', nickname = 'joe', age = 18, birthday = date.today(), appointment = datetime.now() ) Note you don't have to declare all the fields if you don't want to. Omitted fields will be generated automatically. The variable `person` serves as the recipe name: .. code-block:: python from model_mommy import mommy mommy.make_recipe('family.person') Or if you don't want a persisted instance: .. code-block:: python from model_mommy import mommy mommy.prepare_recipe('family.person') You can use the `_quantity` parameter as well if you want to create more than one object from a single recipe. You can define recipes locally to your module or test case as well. This can be useful for cases where a particular set of values may be unique to a particular test case, but used repeatedly there. .. code-block:: python company_recipe = Recipe(Company, name='WidgetCo') class EmployeeTest(TestCase): def setUp(self): self.employee_recipe = Recipe( Employee, name=seq('Employee '), company=company_recipe.make()) def test_employee_list(self): self.employee_recipe.make(_quantity=3) # test stuff.... def test_employee_tasks(self): employee1 = self.employee_recipe.make() task_recipe = Recipe(Task, employee=employee1) task_recipe.make(status='done') task_recipe.make(due_date=datetime(2014, 1, 1)) # test stuff.... Recipes with foreign keys ------------------------- You can define `foreign_key` relations: .. code-block:: python from model_mommy.recipe import Recipe, foreign_key from family.models import Person, Dog person = Recipe(Person, name = 'John Doe', nickname = 'joe', age = 18, birthday = date.today(), appointment = datetime.now() ) dog = Recipe(Dog, breed = 'Pug', owner = foreign_key(person) ) Notice that `person` is a *recipe*. You may be thinking: "I can put the Person model instance directly in the owner field". That's not recommended. Using the `foreign_key` is important for 2 reasons: * Semantics. You'll know that attribute is a foreign key when you're reading; * The associated instance will be created only when you call `make_recipe` and not during recipe definition; Recipes with callables ---------------------- It's possible to use *callables* as recipe's attribute value. .. code-block:: python from datetime import date from model_mommy.recipe import Recipe from family.models import Person person = Recipe(Person, birthday = date.today, ) When you call `make_recipe`, *Mommy* will set the attribute to the value returned by the callable. Sequences in recipes ---------------------- Sometimes, you have a field with an unique value and using `make` can cause random errors. Also, passing an attribute value just to avoid uniqueness validation problems can be tedious. To solve this you can define a sequence with `seq` .. code-block:: python from model_mommy.recipe import Recipe, seq from family.models import Person person = Recipe(Person, name = seq('Joe'), age = seq(15) ) p = mommy.make_recipe('myapp.person') p.name >>> 'Joe1' p.age >>> 16 p = mommy.make_recipe('myapp.person') p.name >>> 'Joe2' p.age >>> 17 This will append a counter to strings to avoid uniqueness problems and it will sum the counter with numerical values. You can also provide an optional `increment_by` argument which will modify incrementing behaviour. This can be an integer, float or Decimal. .. code-block:: python person = Recipe(Person, age = seq(15, increment_by=3) height_ft = seq(5.5, increment_by=.25) ) p = mommy.make_recipe('myapp.person') p.age >>> 18 p.height_ft >>> 5.75 p = mommy.make_recipe('myapp.person') p.age >>> 21 p.height_ft >>> 6.0 Overriding recipe definitions ----------------------------- Passing values when calling `make_recipe` or `prepare_recipe` will override the recipe rule. .. code-block:: python from model_mommy import mommy mommy.make_recipe('model_mommy.person', name='Peter Parker') This is useful when you have to create multiple objects and you have some unique field, for instance. Deprecation Warnings ==================== Because of the changes of model_mommy's API, the following methods are deprecated and will be removed in one of the future releases: * `mommy.make_one` -> should use the method `mommy.make` instead * `mommy.prepare_one` -> should use the method `mommy.prepare` instead * `mommy.make_many` -> should use the method `mommy.make` with the `_quantity` parameter instead * `mommy.make_many_from_recipe` -> should use the method `mommy.make_recipe` with the `_quantity` parameter instead Known Issues ============ django-taggit ------------- Model-mommy identifies django-taggit's `TaggableManager` as a normal Django field, which can lead to errors: .. code-block:: pycon TypeError: is not supported by mommy. The fix for this is to set ``blank=True`` on your ``TaggableManager``. Extensions ========== GeoDjango --------- Works with it? This project has some custom generators for it: https://github.com/sigma-consultoria/mommy_spatial_generators Contributing ============ 1. Prepare a virtual environment. .. code-block:: console pip install virtualenvwrapper mkvirtualenv --no-site-packages --distribute 2. Install the requirements. .. code-block:: console pip install -r requirements.txt 3. Run the tests. .. code-block:: console make test Inspiration =========== *Model-mommy* was inspired by many great open source software like ruby's ObjectDaddy and FactoryGirl. Doubts? Loved it? Hated it? Suggestions? ======================================== Join our mailing list for support, development and ideas! * https://groups.google.com/group/model-mommy Keywords: django testing factory python Platform: UNKNOWN Classifier: Framework :: Django Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Topic :: Software Development model_mommy-1.2/model_mommy/0000755000175000017500000000000012237016123020225 5ustar vandersonvanderson00000000000000model_mommy-1.2/model_mommy/mock_file.txt0000644000175000017500000000001212163352632022715 0ustar vandersonvanderson00000000000000mock file model_mommy-1.2/model_mommy/timezone.py0000644000175000017500000000075212163352632022443 0ustar vandersonvanderson00000000000000# coding: utf-8 ''' Add support for Django 1.4+ safe datetimes. https://docs.djangoproject.com/en/1.4/topics/i18n/timezones/ ''' from datetime import datetime from django import VERSION from django.conf import settings try: from django.utils.timezone import now, utc except ImportError: now = lambda: datetime.now() def smart_datetime(*args): value = datetime(*args) if VERSION >= (1, 4) and settings.USE_TZ: value = value.replace(tzinfo=utc) return value model_mommy-1.2/model_mommy/recipe.py0000644000175000017500000000406512235440324022055 0ustar vandersonvanderson00000000000000#coding: utf-8 import inspect from . import mommy from .exceptions import RecipeNotFound from six import string_types class Recipe(object): def __init__(self, model, **attrs): self.attr_mapping = attrs self.model = model def _mapping(self, new_attrs): rel_fields_attrs = dict((k, v) for k, v in new_attrs.items() if '__' in k) new_attrs = dict((k, v) for k, v in new_attrs.items() if not '__' in k) mapping = self.attr_mapping.copy() for k, v in self.attr_mapping.items(): # do not generate values if field value is provided if new_attrs.get(k): continue elif isinstance(v, RecipeForeignKey): a={} for key, value in list(rel_fields_attrs.items()): if key.startswith('%s__' % k): a[key] = rel_fields_attrs.pop(key) recipe_attrs = mommy.filter_rel_attrs(k, **a) mapping[k] = v.recipe.make(**recipe_attrs) mapping.update(new_attrs) mapping.update(rel_fields_attrs) return mapping def make(self, **attrs): return mommy.make(self.model, **self._mapping(attrs)) def prepare(self, **attrs): return mommy.prepare(self.model, **self._mapping(attrs)) class RecipeForeignKey(object): def __init__(self, recipe): if isinstance(recipe, Recipe): self.recipe = recipe elif isinstance(recipe, string_types): frame = inspect.stack()[2] caller_module = inspect.getmodule(frame[0]) recipe = getattr(caller_module, recipe) if recipe: self.recipe = recipe else: raise RecipeNotFound else: raise TypeError('Not a recipe') def foreign_key(recipe): """ Returns the callable, so that the associated model will not be created during the recipe definition. """ return RecipeForeignKey(recipe) def seq(value, increment_by=1): return mommy.Sequence(value, increment_by=increment_by) model_mommy-1.2/model_mommy/exceptions.py0000644000175000017500000000031212163352632022762 0ustar vandersonvanderson00000000000000#coding:utf-8 class RecipeNotFound(Exception): pass class ModelNotFound(Exception): pass class AmbiguousModelName(Exception): pass class InvalidQuantityException(Exception): pass model_mommy-1.2/model_mommy/generators.py0000644000175000017500000000613112235440324022753 0ustar vandersonvanderson00000000000000# -*- coding:utf-8 -*- """ Generators are callables that return a value used to populate a field. If this callable has a `required` attribute (a list, mostly), for each item in the list, if the item is a string, the field attribute with the same name will be fetched from the field and used as argument for the generator. If it is a callable (which will receive `field` as first argument), it should return a list in the format (key, value) where key is the argument name for generator and value is the value for that argument. """ import string from decimal import Decimal from os.path import abspath, join, dirname from random import randint, choice, random from django import VERSION from django.contrib.contenttypes.models import ContentType from django.core.files.base import ContentFile from django.db.models import get_models from model_mommy.timezone import now MAX_LENGTH = 300 # Using sys.maxint here breaks a bunch of tests when running against a # Postgres database. MAX_INT = 10000 def get_content_file(content, name): if VERSION < (1, 4): return ContentFile(content) else: return ContentFile(content, name=name) def gen_file_field(): name = u'mock_file.txt' file_path = abspath(join(dirname(__file__), name)) with open(file_path, 'rb') as f: return get_content_file(f.read(), name=name) def gen_image_field(): name = u'mock-img.jpeg' file_path = abspath(join(dirname(__file__), name)) with open(file_path, 'rb') as f: return get_content_file(f.read(), name=name) def gen_from_list(L): '''Makes sure all values of the field are generated from the list L Usage: from mommy import Mommy class KidMommy(Mommy): attr_mapping = {'some_field':gen_from_list([A, B, C])} ''' return lambda: choice(list(L)) # -- DEFAULT GENERATORS -- def gen_from_choices(C): choice_list = map(lambda x: x[0], C) return gen_from_list(choice_list) def gen_integer(min_int=-MAX_INT, max_int=MAX_INT): return randint(min_int, max_int) def gen_float(): return random() * gen_integer() def gen_decimal(max_digits, decimal_places): num_as_str = lambda x: ''.join([str(randint(0, 9)) for i in range(x)]) return Decimal("%s.%s" % (num_as_str(max_digits - decimal_places), num_as_str(decimal_places))) gen_decimal.required = ['max_digits', 'decimal_places'] def gen_date(): return now().date() def gen_datetime(): return now() def gen_time(): return now().time() def gen_string(max_length): return u''.join(choice(string.ascii_letters) for i in range(max_length)) gen_string.required = ['max_length'] def gen_slug(max_length=50): valid_chars = string.ascii_letters + string.digits + '_-' return u''.join(choice(valid_chars) for i in range(max_length)) def gen_text(): return gen_string(MAX_LENGTH) def gen_boolean(): return choice((True, False)) def gen_url(): return u'http://www.%s.com' % gen_string(30) def gen_email(): return u"%s@example.com" % gen_string(10) def gen_content_type(): return ContentType.objects.get_for_model(choice(get_models())) model_mommy-1.2/model_mommy/mock-img.jpeg0000644000175000017500000000357412163352632022616 0ustar vandersonvanderson00000000000000JFIF  ! '(*%$%"/,#3)8,/ 25<,A27-5 2$$-,4./50,,/55)5.4*4*,,)),))-.4),)),,,,),),),,)))),)8">!1AQa"qt2Srs%46T#$5B !1AQa" ?sWN;TY!U3d?Vz|Vv&j*ȭ. T.:hAgn`(KNP= P*#t,\JwݽsߵB*h)CJRR(rVkiD.!~҅-|{ɱw8m*'JX' xW|E4vPB;L$N}9oW'PiJ!ư&)fvLWEAqC~Y zԾKݵ>yT  r>O]akMq nG+#ȟz| -55)W@#F =Xod;Z! MHQRH9#:T/C 4[c̆w}0ߨGxk 72*b6u$1ު>Z9HDeadbez xc~?2j̶9pAQ %=ۇ$w]:K(UI6PO^鎹2rZqS?u$š15c_5B*'a=aEIe❜pK*0R$~Pz{zd[t}xAӕŤDFqMf+}KRyiwp"c]ʤ;HCWF7[?67Hm+{}֏<\s$*\OVP;Phrg-Ѵ*e ]Y‡ ;=+a=gILH"4v/r*;:JMd2F^eK0luK4dsᝀGZ޽qX{o[ D<:bmJG,S) 0G=׌Hu B[W "5P}Ϲ5PÕxjVӴNVfPDiIv^'۽BnZYI͘^U9u)C3C?O:Hb,yRdy:|YR)JR)@~XHJI9>(S)JW+LҦGopW?{JPV^ "':vl]FF|OsJR⏣model_mommy-1.2/model_mommy/__init__.py0000644000175000017500000000016512237016053022342 0ustar vandersonvanderson00000000000000#coding:utf-8 __version__ = '1.2' __title__ = 'model_mommy' __author__ = 'Vanderson Mota' __license__ = 'Apache 2.0' model_mommy-1.2/model_mommy/mommy.py0000644000175000017500000003444612235440324021752 0ustar vandersonvanderson00000000000000# -*- coding: utf-8 -*- import warnings from django.conf import settings from django.utils import importlib from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType from django.db.models.loading import cache, get_model from django.db.models.base import ModelBase from django.db.models import (\ CharField, EmailField, SlugField, TextField, URLField, DateField, DateTimeField, TimeField, AutoField, IntegerField, SmallIntegerField, PositiveIntegerField, PositiveSmallIntegerField, BooleanField, DecimalField, FloatField, FileField, ImageField, Field, ForeignKey, ManyToManyField, OneToOneField) try: from django.db.models import BigIntegerField except ImportError: BigIntegerField = IntegerField from . import generators from .exceptions import ModelNotFound, AmbiguousModelName, InvalidQuantityException from six import string_types class Sequence(object): def __init__(self, value, increment_by=1): self.value = value self.counter = increment_by self.increment_by = increment_by def get_inc(self, model): if not model.objects.count(): self.counter = self.increment_by i = self.counter self.counter += self.increment_by return i def gen(self, model): inc = self.get_inc(model) return self.value + type(self.value)(inc) recipes = None # FIXME: use pkg_resource from os.path import dirname, join mock_file_jpeg = join(dirname(__file__), 'mock-img.jpeg') mock_file_txt = join(dirname(__file__), 'mock_file.txt') #TODO: improve related models handling foreign_key_required = [lambda field: ('model', field.related.parent_model)] MAX_MANY_QUANTITY = 5 def make(model, _quantity=None, make_m2m=False, **attrs): """ Creates a persisted instance from a given model its associated models. It fill the fields with random values or you can specify which fields you want to define its values by yourself. """ mommy = Mommy(model, make_m2m=make_m2m) if _quantity and (not isinstance(_quantity, int) or _quantity < 1): raise InvalidQuantityException if _quantity: return [mommy.make(**attrs) for i in range(_quantity)] else: return mommy.make(**attrs) def prepare(model, _quantity=None, **attrs): """ Creates a BUT DOESN'T persist an instance from a given model its associated models. It fill the fields with random values or you can specify which fields you want to define its values by yourself. """ mommy = Mommy(model) if _quantity and (not isinstance(_quantity, int) or _quantity < 1): raise InvalidQuantityException if _quantity: return [mommy.prepare(**attrs) for i in range(_quantity)] else: return mommy.prepare(**attrs) def _recipe(name): app, recipe_name = name.rsplit('.', 1) recipes = importlib.import_module('.'.join([app, 'mommy_recipes'])) return getattr(recipes, recipe_name) def make_recipe(mommy_recipe_name, _quantity=None, **new_attrs): return _recipe(mommy_recipe_name).make(_quantity=_quantity, **new_attrs) def prepare_recipe(mommy_recipe_name, _quantity=None, **new_attrs): return _recipe(mommy_recipe_name).prepare(_quantity=_quantity, **new_attrs) def __m2m_generator(model, **attrs): return make(model, _quantity=MAX_MANY_QUANTITY, **attrs) make.required = foreign_key_required prepare.required = foreign_key_required __m2m_generator.required = foreign_key_required default_mapping = { BooleanField: generators.gen_boolean, IntegerField: generators.gen_integer, BigIntegerField: generators.gen_integer, SmallIntegerField: generators.gen_integer, PositiveIntegerField: lambda: generators.gen_integer(0), PositiveSmallIntegerField: lambda: generators.gen_integer(0), FloatField: generators.gen_float, DecimalField: generators.gen_decimal, CharField: generators.gen_string, TextField: generators.gen_text, SlugField: generators.gen_slug, ForeignKey: make, OneToOneField: make, ManyToManyField: __m2m_generator, DateField: generators.gen_date, DateTimeField: generators.gen_datetime, TimeField: generators.gen_time, URLField: generators.gen_url, EmailField: generators.gen_email, FileField: generators.gen_file_field, ImageField: generators.gen_image_field, ContentType: generators.gen_content_type, } class ModelFinder(object): ''' Encapsulates all the logic for finding a model to Mommy. ''' _unique_models = None _ambiguous_models = None def get_model(self, name): ''' Get a model. :param name String on the form 'applabel.modelname' or 'modelname'. :return a model class. ''' if '.' in name: app_label, model_name = name.split('.') model = get_model(app_label, model_name) else: model = self.get_model_by_name(name) if not model: raise ModelNotFound("Could not find model '%s'." % name.title()) return model def get_model_by_name(self, name): ''' Get a model by name. If a model with that name exists in more than one app, raises AmbiguousModelName. ''' name = name.lower() if self._unique_models is None: self._populate() if name in self._ambiguous_models: raise AmbiguousModelName('%s is a model in more than one app. ' 'Use the form "app.model".' % name.title()) return self._unique_models.get(name) def _populate(self): ''' Cache models for faster self._get_model. ''' unique_models = {} ambiguous_models = [] for app_model in cache.app_models.values(): for name, model in app_model.items(): if name not in unique_models: unique_models[name] = model else: ambiguous_models.append(name) for name in ambiguous_models: unique_models.pop(name, None) self._ambiguous_models = ambiguous_models self._unique_models = unique_models class Mommy(object): attr_mapping = {} type_mapping = None # Note: we're using one finder for all Mommy instances to avoid # rebuilding the model cache for every make_* or prepare_* call. finder = ModelFinder() def __init__(self, model, make_m2m=False): self.make_m2m = make_m2m self.m2m_dict = {} if isinstance(model, ModelBase): self.model = model else: self.model = self.finder.get_model(model) self.init_type_mapping() def init_type_mapping(self): self.type_mapping = default_mapping.copy() generator_from_settings = getattr(settings, 'MOMMY_CUSTOM_FIELDS_GEN', {}) for k, v in generator_from_settings.items(): path, field_name = k.rsplit('.', 1) field_class = getattr(importlib.import_module(path), field_name) self.type_mapping[field_class] = v def make(self, **attrs): '''Creates and persists an instance of the model associated with Mommy instance.''' return self._make(commit=True, **attrs) def prepare(self, **attrs): '''Creates, but do not persists, an instance of the model associated with Mommy instance.''' self.type_mapping[ForeignKey] = prepare return self._make(commit=False, **attrs) def get_fields(self): return self.model._meta.fields + self.model._meta.many_to_many def _make(self, commit=True, **attrs): is_rel_field = lambda x: '__' in x model_attrs = dict((k, v) for k, v in attrs.items() if not is_rel_field(k)) self.rel_attrs = dict((k, v) for k, v in attrs.items() if is_rel_field(k)) self.rel_fields = [x.split('__')[0] for x in self.rel_attrs.keys() if is_rel_field(x)] for field in self.get_fields(): # Skip links to parent so parent is not created twice. if isinstance(field, OneToOneField) and field.rel.parent_link: continue field_value_not_defined = field.name not in model_attrs if isinstance(field, (AutoField, generic.GenericRelation)): continue if all([field.name not in model_attrs, field.name not in self.rel_fields, field.name not in self.attr_mapping]): if not issubclass(field.__class__, Field) or field.has_default() or field.blank: continue if isinstance(field, ManyToManyField): if field.name not in model_attrs: self.m2m_dict[field.name] = self.m2m_value(field) else: self.m2m_dict[field.name] = model_attrs.pop(field.name) elif field_value_not_defined: if field.name not in self.rel_fields and field.null: continue else: model_attrs[field.name] = self.generate_value(field) elif isinstance(model_attrs[field.name], Sequence): model_attrs[field.name] = model_attrs[field.name].gen(self.model) elif callable(model_attrs[field.name]): model_attrs[field.name] = model_attrs[field.name]() return self.instance(model_attrs, _commit=commit) def m2m_value(self, field): if field.name in self.rel_fields: return self.generate_value(field) if not self.make_m2m or field.null: return [] return self.generate_value(field) def instance(self, attrs, _commit): instance = self.model(**attrs) # m2m only works for persisted instances if _commit: instance.save() self._handle_m2m(instance) return instance def _handle_m2m(self, instance): for key, values in self.m2m_dict.items(): if not values: continue m2m_relation = getattr(instance, key) through_model = m2m_relation.through through_fields = through_model._meta.fields instance_key, value_key = '', '' for field in through_fields: if isinstance(field, ForeignKey): if isinstance(instance, field.rel.to): instance_key = field.name elif isinstance(values[0], field.rel.to): value_key = field.name base_kwargs = {instance_key: instance} for model_instance in values: base_kwargs[value_key] = model_instance make(through_model, **base_kwargs) def generate_value(self, field): ''' Calls the generator associated with a field passing all required args. Generator Resolution Precedence Order: -- attr_mapping - mapping per attribute name -- choices -- mapping from avaiable field choices -- type_mapping - mapping from user defined type associated generators -- default_mapping - mapping from pre-defined type associated generators `attr_mapping` and `type_mapping` can be defined easely overwriting the model. ''' if field.name in self.attr_mapping: generator = self.attr_mapping[field.name] elif getattr(field, 'choices'): generator = generators.gen_from_choices(field.choices) elif isinstance(field, ForeignKey) and isinstance(field.rel.to, ContentType): generator = self.type_mapping[ContentType] elif field.__class__ in self.type_mapping: generator = self.type_mapping[field.__class__] else: raise TypeError('%s is not supported by mommy.' % field.__class__) # attributes like max_length, decimal_places are take in account when # generating the value. generator_attrs = get_required_values(generator, field) if field.name in self.rel_fields: generator_attrs.update(filter_rel_attrs(field.name, **self.rel_attrs)) return generator(**generator_attrs) def get_required_values(generator, field): ''' Gets required values for a generator from the field. If required value is a function, call's it with field as argument. If required value is a string, simply fetch the value from the field and returns. ''' #FIXME: avoid abreviations rt = {} if hasattr(generator, 'required'): for item in generator.required: if callable(item): # mommy can deal with the nasty hacking too! key, value = item(field) rt[key] = value elif isinstance(item, string_types): rt[item] = getattr(field, item) else: raise ValueError("Required value '%s' is of wrong type. \ Don't make mommy sad." % str(item)) return rt def filter_rel_attrs(field_name, **rel_attrs): clean_dict = {} for k, v in rel_attrs.items(): if k.startswith(field_name + '__'): splited_key = k.split('__') key = '__'.join(splited_key[1:]) clean_dict[key] = v else: clean_dict[k] = v return clean_dict ### DEPRECATED METHODS (should be removed on the future) def make_many(model, quantity=None, **attrs): msg = "make_many is deprecated. You should use make with _quantity parameter." warnings.warn(msg, DeprecationWarning) quantity = quantity or MAX_MANY_QUANTITY mommy = Mommy(model) return [mommy.make(**attrs) for i in range(quantity)] def make_one(model, make_m2m=False, **attrs): msg = "make_one is deprecated. You should use the method make instead." warnings.warn(msg, DeprecationWarning) mommy = Mommy(model, make_m2m=make_m2m) return mommy.make(**attrs) def prepare_one(model, **attrs): msg = "prepare_one is deprecated. You should use the method prepare instead." warnings.warn(msg, DeprecationWarning) mommy = Mommy(model) return mommy.prepare(**attrs) def make_many_from_recipe(mommy_recipe_name, quantity=None, **new_attrs): msg = "make_many_from_recipe is deprecated. You should use the method make_recipe with the _quantity parameter instead." warnings.warn(msg, DeprecationWarning) quantity = quantity or MAX_MANY_QUANTITY return [make_recipe(mommy_recipe_name, **new_attrs) for x in range(quantity)]