Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
klen committed Sep 28, 2018
2 parents 65ab3bd + 1229257 commit b314ba5
Show file tree
Hide file tree
Showing 16 changed files with 113 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
@@ -1,6 +1,6 @@
[bumpversion]
commit = True
current_version = 6.0.1
current_version = 6.1.0
files = mixer/__init__.py
tag = True
tag_name = {new_version}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -15,3 +15,4 @@
/todo.txt
dist
docs/_build
.pytest_cache
4 changes: 4 additions & 0 deletions Changelog
@@ -1,3 +1,7 @@
2018-09-25

* mixer.unregister_middleware

2017-11-06 marazmiki

* Added Django 2.0 support for Python 3.6;
Expand Down
9 changes: 8 additions & 1 deletion README.rst
Expand Up @@ -56,11 +56,12 @@ documentation enhancements and/or fixes are awesome and most welcome.**
Requirements
=============

- Django (1.10, 1.11, 2.0) for Django ORM support;
- Django (1.11, 2.1) for Django ORM support;
- Faker >= 0.7.3
- Flask-SQLALchemy for SQLAlchemy ORM support and integration as Flask application;
- Mongoengine for Mongoengine ODM support;
- SQLAlchemy for SQLAlchemy ORM support;
- Peewee ORM support;
- fake-factory >= 0.5.0
- faker == 0.7.3
- python 2.7 or 3.6+
Expand Down Expand Up @@ -319,6 +320,11 @@ You can add middleware layers to process generation: ::
You can add several middlewares. Each middleware should get one argument
(generated value) and return them.

It's also possible to unregister a middleware: ::

mixer.unregister_middleware(encrypt_password)


Locales
-------

Expand Down Expand Up @@ -381,6 +387,7 @@ Contributors
* Mikhail Porokhovnichenko (https://github.com/marazmiki)
* Skylar Saveland (https://github.com/skyl)
* Suriya Subramanian (https://github.com/suriya)
* Gram (https://github.com/orsinium)

License
=======
Expand Down
8 changes: 4 additions & 4 deletions docs/quickstart.rst
Expand Up @@ -7,7 +7,7 @@ Quickstart

.. currentmodule:: mixer.main

Mixer is easy to use and realy fun for testing applications.
Mixer is easy to use and really fun for testing applications.
Module has a common api for all backends (Django_, Flask_).

Django ORM
Expand Down Expand Up @@ -43,10 +43,10 @@ Base Usage

You can use class or string with model name.

.. [1] Model name supports two formats. Use 'app_name.model_name' for prevent conflicts.
.. [1] Model name supports two formats. Use 'app_name.model_name' for preventing conflicts.
Or you can use just 'model_name' for models with unique names.
.. [2] `model_name` is case insensitive.
.. [2] `model_name` is case-insensitive.
.. code-block:: python
Expand Down Expand Up @@ -130,7 +130,7 @@ SQLAlchemy ORM
Support for Flask-SQLAlchemy models that have `__init__` arguments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For support this scheme, just create your own mixer class, like this: ::
To support this scheme, just create your own mixer class, like this: ::

from mixer.backend.sqlalchemy import Mixer

Expand Down
2 changes: 1 addition & 1 deletion mixer/__init__.py
Expand Up @@ -14,7 +14,7 @@
# Module information
# ==================

__version__ = "6.0.1"
__version__ = "6.1.0"
__project__ = "mixer"
__author__ = "horneds <horneds@gmail.com>"
__license__ = "BSD"
2 changes: 1 addition & 1 deletion mixer/backend/django.py
Expand Up @@ -229,7 +229,7 @@ def _get_value(self, name, value, field=None):
if callable(value):
return self._get_value(name, value(), field)

if field:
if field and not isinstance(field.scheme, models.ForeignKey):
value = field.scheme.to_python(value)

return name, value
Expand Down
9 changes: 7 additions & 2 deletions mixer/backend/peewee.py
Expand Up @@ -8,6 +8,11 @@
from __future__ import absolute_import

from peewee import * # noqa
try:
from peewee import AutoField
except ImportError:
from peewee import PrimaryKeyField as AutoField

import datetime
import decimal

Expand Down Expand Up @@ -39,7 +44,7 @@ class GenFactory(BaseFactory):
""" Map a peewee classes to simple types. """

types = {
PrimaryKeyField: t.PositiveInteger,
AutoField: t.PositiveInteger,
IntegerField: int,
BigIntegerField: t.BigInteger,
(FloatField, DoubleField): float,
Expand Down Expand Up @@ -75,7 +80,7 @@ def populate_target(self, values):

def gen_field(self, field):
""" Function description. """
if isinstance(field.scheme, PrimaryKeyField)\
if isinstance(field.scheme, AutoField)\
and self.__mixer and self.__mixer.params.get('commit'):
return field.name, SKIP_VALUE
return super(TypeMixer, self).gen_field(field)
Expand Down
5 changes: 3 additions & 2 deletions mixer/factory.py
Expand Up @@ -119,9 +119,10 @@ class GenFactory(_.with_metaclass(GenFactoryMeta)):
('time_zone', str): faker.timezone,
('timezone', str): faker.timezone,
('title', str): faker.title,
('url', t.URL): faker.uri,
('url', str): faker.uri,
('url', t.URL): faker.uri,
('username', str): faker.user_name,
('uuid', None): faker.uuid,
}

types = {
Expand Down Expand Up @@ -169,7 +170,7 @@ def get_fabric(cls, fcls, fname=None, fake=False):
simple = cls.cls_to_simple(fcls)
func = cls.generators.get(fcls) or cls.generators.get(simple)

if not func and fcls.__bases__:
if not func and fcls and fcls.__bases__:
func = cls.generators.get(fcls.__bases__[0])

if fname and fake and (fname, simple) in cls.fakers:
Expand Down
12 changes: 10 additions & 2 deletions mixer/main.py
Expand Up @@ -556,10 +556,10 @@ def blend(self, scheme, **values):
mixer = Mixer()
mixer.blend(SomeSheme, active=True)
mixer.blend(SomeScheme, active=True)
print scheme.active # True
mixer.blend('module.SomeSheme', active=True)
mixer.blend('module.SomeScheme', active=True)
print scheme.active # True
"""
Expand Down Expand Up @@ -711,6 +711,14 @@ def wrapper(middleware):

return wrapper

def unregister_middleware(self, scheme, middleware):
"""Remove middleware from scheme
"""
type_mixer = self.type_mixer_cls(
scheme, mixer=self, fake=self.params.get('fake'),
factory=self.__factory)
type_mixer.middlewares.remove(middleware)

def register(self, scheme, **params):
""" Manualy register a function as value's generator for class.field.
Expand Down
5 changes: 3 additions & 2 deletions requirements-tests.txt
@@ -1,11 +1,12 @@
Django >= 1.10.3
Django >= 2.1.1
Flask >= 0.11.1
Marshmallow >= 2.10.3
SQLAlchemy >= 1.1.4
flask-sqlalchemy >= 2.1
ipdb >= 0.10.3
mongoengine >= 0.10.1
peewee >= 2.8.5
peewee >= 3.7.0
pony >= 0.7
psycopg2 >= 2.7.5
pytest >= 3.0.4
pytest-sugar >= 0.7.1
66 changes: 34 additions & 32 deletions tests/test_auto.py
Expand Up @@ -6,52 +6,54 @@ def test_main():

assert mixer

# def test_django(self):
# from django.core.management import call_command
# from mixer.auto import mixer

# from .django_app.models import Rabbit
def test_django():
from django.core.management import call_command
from mixer.auto import mixer

from .django_app.models import Rabbit

# call_command('syncdb', interactive=False)
call_command('migrate', interactive=False)

# rabbit = mixer.blend(Rabbit)
# self.assertTrue(rabbit)
rabbit = mixer.blend(Rabbit)
assert rabbit

# rabbit = mixer.blend('tests.django_app.models.Rabbit')
# self.assertTrue(rabbit)
rabbit = mixer.blend('tests.django_app.models.Rabbit')
assert rabbit

# rabbits = mixer.cycle(2).blend(Rabbit)
# self.assertTrue(all(rabbits))
rabbits = mixer.cycle(2).blend(Rabbit)
assert all(rabbits)

# call_command('flush', interactive=False)
call_command('flush', interactive=False)

# def test_sqlalchemy(self):
# from mixer.auto import mixer

# from .test_sqlalchemy import User
def test_sqlalchemy():
from mixer.auto import mixer
from .test_sqlalchemy import User

# user = mixer.blend(User)
# self.assertTrue(user)
user = mixer.blend(User)
assert user

# user = mixer.blend('tests.test_sqlalchemy.User')
# self.assertTrue(user)
user = mixer.blend('tests.test_sqlalchemy.User')
assert user

# users = mixer.cycle(2).blend(User)
# self.assertTrue(all(users))
users = mixer.cycle(2).blend(User)
assert all(users)

# def test_mongoengine(self):
# from mixer.backend.mongoengine import mixer as m
# m.params['commit'] = False

# from mixer.auto import mixer
def test_mongoengine():
from mixer.backend.mongoengine import mixer as m
m.params['commit'] = False

from mixer.auto import mixer

# from .test_mongoengine import User
from .test_mongoengine import User

# user = mixer.blend(User)
# self.assertTrue(user)
user = mixer.blend(User)
assert user

# user = mixer.blend('tests.test_mongoengine.User')
# self.assertTrue(user)
user = mixer.blend('tests.test_mongoengine.User')
assert user

# users = mixer.cycle(2).blend(User)
# self.assertTrue(all(users))
users = mixer.cycle(2).blend(User)
assert all(users)
1 change: 0 additions & 1 deletion tests/test_django.py
Expand Up @@ -30,7 +30,6 @@ def test_fields(mixer):
assert isinstance(rabbit, Rabbit)
assert rabbit.id
assert rabbit.pk
assert rabbit.pk == 1
assert len(rabbit.title) <= 16
assert isinstance(rabbit.active, bool)
assert isinstance(rabbit.object_id, int)
Expand Down
10 changes: 8 additions & 2 deletions tests/test_main.py
Expand Up @@ -261,16 +261,22 @@ def test_locale():
def test_silence():
mixer = Mixer()

class CustomException(Exception):
pass

@mixer.middleware(Test)
def falsed(test): # noqa
raise Exception('Unhandled')
raise CustomException('Unhandled')

with pytest.raises(Exception):
with pytest.raises(CustomException):
mixer.blend(Test)

with mixer.ctx(silence=True):
mixer.blend(Test)

mixer.unregister_middleware(Test, falsed)
mixer.blend(Test) # does not raise any exceptions


def test_guard():
mixer = Mixer()
Expand Down
22 changes: 21 additions & 1 deletion tests/test_sqlalchemy.py
Expand Up @@ -59,7 +59,8 @@ class User(BASE):
enum = Column(Enum('one', 'two'), nullable=False)
random = Column(Integer, default=lambda: randrange(993, 995))
profile_id = Column(Integer, ForeignKey('profile.id'), nullable=False)
profile_id_nonincremental = Column(Integer, ForeignKey('profile_nonincremental.id'), nullable=False)
profile_id_nonincremental = Column(
Integer, ForeignKey('profile_nonincremental.id'), nullable=False)
augmented = Column(AugmentedType, default='augmented', nullable=False)


Expand Down Expand Up @@ -132,6 +133,7 @@ def test_mixer(session):
user = mixer.blend(User, username=lambda: 'callable_value')
assert user.username == 'callable_value'


def test_cycle(session):
from mixer.backend.sqlalchemy import Mixer

Expand All @@ -143,6 +145,7 @@ def test_cycle(session):
assert users[0].profile.name == 'first'
assert users[1].profile.name == 'second'


def test_select(session):
from mixer.backend.sqlalchemy import Mixer

Expand Down Expand Up @@ -211,3 +214,20 @@ def test_nonincremental_primary_key(session):

test = mixer.blend(ProfileNonIncremental, id=42)
assert test.name


def test_postgresql():
from mixer.backend.sqlalchemy import TypeMixer
from sqlalchemy.dialects.postgresql import UUID

base = declarative_base()

class Test(base):
__tablename__ = 'test'

id = Column(Integer, primary_key=True)
uuid = Column(UUID, nullable=False)

mixer = TypeMixer(Test)
test = mixer.blend()
assert test.uuid

0 comments on commit b314ba5

Please sign in to comment.