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

Add MixinDocument #278

Merged
merged 2 commits into from
Jul 20, 2020
Merged
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
54 changes: 53 additions & 1 deletion tests/frameworks/test_motor_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

from ..common import BaseDBTest, TEST_DB

from umongo import Document, EmbeddedDocument, fields, exceptions, Reference
from umongo import (
Document, EmbeddedDocument, MixinDocument, fields, exceptions, Reference
)

if not dep_error: # Make sure the module is valid by importing it
from umongo.frameworks import motor_asyncio as framework # noqa
Expand Down Expand Up @@ -954,3 +956,53 @@ def pre_delete(self):
await p.delete()

loop.run_until_complete(do_test())

def test_mixin_pre_post_hooks(self, loop, instance):

async def do_test():

callbacks = []

@instance.register
class PrePostHooksMixin(MixinDocument):

def pre_insert(self):
callbacks.append('pre_insert')

def pre_update(self):
callbacks.append('pre_update')

def pre_delete(self):
callbacks.append('pre_delete')

def post_insert(self, ret):
assert isinstance(ret, InsertOneResult)
callbacks.append('post_insert')

def post_update(self, ret):
assert isinstance(ret, UpdateResult)
callbacks.append('post_update')

def post_delete(self, ret):
assert isinstance(ret, DeleteResult)
callbacks.append('post_delete')

@instance.register
class Person(PrePostHooksMixin, Document):
name = fields.StrField()
age = fields.IntField()

p = Person(name='John', age=20)
await p.commit()
assert callbacks == ['pre_insert', 'post_insert']

callbacks.clear()
p.age = 22
await p.commit({'age': 22})
assert callbacks == ['pre_update', 'post_update']

callbacks.clear()
await p.delete()
assert callbacks == ['pre_delete', 'post_delete']

loop.run_until_complete(do_test())
52 changes: 50 additions & 2 deletions tests/frameworks/test_pymongo.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timezone

import pytest

Expand All @@ -7,7 +7,9 @@
from pymongo.results import InsertOneResult, UpdateResult, DeleteResult
import marshmallow as ma

from umongo import Document, EmbeddedDocument, fields, exceptions, Reference
from umongo import (
Document, EmbeddedDocument, MixinDocument, fields, exceptions, Reference
)
from umongo.frameworks import pymongo as framework_pymongo # noqa

from ..common import BaseDBTest, TEST_DB
Expand Down Expand Up @@ -746,3 +748,49 @@ def pre_delete(self):
with pytest.raises(exceptions.DeleteError):
p_concurrent.delete()
p.delete()

def test_mixin_pre_post_hooks(self, instance):

callbacks = []

@instance.register
class PrePostHooksMixin(MixinDocument):

def pre_insert(self):
callbacks.append('pre_insert')

def pre_update(self):
callbacks.append('pre_update')

def pre_delete(self):
callbacks.append('pre_delete')

def post_insert(self, ret):
assert isinstance(ret, InsertOneResult)
callbacks.append('post_insert')

def post_update(self, ret):
assert isinstance(ret, UpdateResult)
callbacks.append('post_update')

def post_delete(self, ret):
assert isinstance(ret, DeleteResult)
callbacks.append('post_delete')

@instance.register
class Person(PrePostHooksMixin, Document):
name = fields.StrField()
age = fields.IntField()

p = Person(name='John', age=20)
p.commit()
assert callbacks == ['pre_insert', 'post_insert']

callbacks.clear()
p.age = 22
p.commit()
assert callbacks == ['pre_update', 'post_update']

callbacks.clear()
p.delete()
assert callbacks == ['pre_delete', 'post_delete']
53 changes: 52 additions & 1 deletion tests/frameworks/test_txmongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def wrapper(self):
else:
pytest_inlineCallbacks = pytest_twisted.inlineCallbacks

from umongo import Document, EmbeddedDocument, fields, exceptions, Reference
from umongo import (
Document, EmbeddedDocument, MixinDocument, fields, exceptions, Reference
)


if not dep_error: # Make sure the module is valid by importing it
Expand Down Expand Up @@ -879,3 +881,52 @@ def pre_delete(self):
with pytest.raises(exceptions.DeleteError):
yield p_concurrent.delete()
yield p.delete()

@pytest_inlineCallbacks
def test_mixin_pre_post_hooks(self, instance):

callbacks = []

@instance.register
class PrePostHooksMixin(MixinDocument):

def pre_insert(self):
callbacks.append('pre_insert')

def pre_update(self):
callbacks.append('pre_update')

def pre_delete(self):
callbacks.append('pre_delete')

def post_insert(self, ret):
assert isinstance(ret, InsertOneResult)
callbacks.append('post_insert')

def post_update(self, ret):
assert isinstance(ret, UpdateResult)
callbacks.append('post_update')

def post_delete(self, ret):
assert isinstance(ret, DeleteResult)
callbacks.append('post_delete')

@instance.register
class Person(PrePostHooksMixin, Document):
name = fields.StrField()
age = fields.IntField()

p = Person(name='John', age=20)
yield p.commit()
assert callbacks == ['pre_insert', 'post_insert']

callbacks.clear()
p.age = 22
yield p.commit({'age': 22})
assert callbacks == ['pre_update', 'post_update']

callbacks.clear()
yield p.delete()
assert callbacks == ['pre_delete', 'post_delete']


120 changes: 118 additions & 2 deletions tests/test_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
from bson import ObjectId, DBRef
import marshmallow as ma

from umongo import (Document, EmbeddedDocument, Schema, fields, exceptions,
post_dump, pre_load, validates_schema)
from umongo import (
Document, EmbeddedDocument, MixinDocument,
Schema, fields, exceptions, post_dump, pre_load, validates_schema
)

from .common import BaseTest

Expand Down Expand Up @@ -432,6 +434,120 @@ class User(Document):
with pytest.raises(exceptions.AlreadyCreatedError):
john.update({'primary_key': ObjectId()})

def test_mixin(self):

@self.instance.register
class PMixin(MixinDocument):
pm = fields.IntField()

@self.instance.register
class CMixin(MixinDocument):
cm = fields.IntField()

@self.instance.register
class Parent(PMixin, Document):
p = fields.StrField()

class Meta:
allow_inheritance = True

@self.instance.register
class Child(CMixin, Parent):
c = fields.StrField()

assert set(Parent.schema.fields.keys()) == {'id', 'p', 'pm'}
assert set(Child.schema.fields.keys()) == {'id', 'cls', 'p', 'pm', 'c', 'cm'}

parent_data = {'p': 'parent', 'pm': 42}
child_data = {'c': 'child', 'cm': 12, **parent_data}

assert Parent(**parent_data).dump() == parent_data
assert Child(**child_data).dump() == {**child_data, 'cls': 'Child'}

parent = Parent()
parent.p = 'parent'
parent.pm = 42
assert parent.p == 'parent'
assert parent.pm == 42
assert parent.dump() == parent_data
del parent.p
del parent.pm
assert parent.p is None
assert parent.pm is None

parent = Parent()
parent['p'] = 'parent'
parent['pm'] = 42
assert parent['p'] == 'parent'
assert parent['pm'] == 42
assert parent.dump() == parent_data
del parent['p']
del parent['pm']
assert parent['p'] is None
assert parent['pm'] is None

child = Child()
child.c = 'child'
child.cm = 12
child.p = 'parent'
child.pm = 42
assert child.c == 'child'
assert child.cm == 12
assert child.dump() == {'cls': 'Child', **child_data}
del child.c
del child.cm
assert child.c is None
assert child.cm is None

child = Child()
child['c'] = 'child'
child['cm'] = 12
child['p'] = 'parent'
child['pm'] = 42
assert child['c'] == 'child'
assert child['cm'] == 12
assert child.dump() == {'cls': 'Child', **child_data}
del child['c']
del child['cm']
assert child['c'] is None
assert child['cm'] is None

def test_mixin_override(self):

@self.instance.register
class PMixin(MixinDocument):
pm = fields.IntField()

@self.instance.register
class CMixin(MixinDocument):
cm = fields.IntField()

@self.instance.register
class Parent(PMixin, Document):
p = fields.StrField()
pm = fields.IntField(validate=ma.validate.Range(0, 5))

class Meta:
allow_inheritance = True

@self.instance.register
class Child(CMixin, Parent):
c = fields.StrField()
cm = fields.IntField(validate=ma.validate.Range(0, 5))

assert set(Parent.schema.fields.keys()) == {'id', 'p', 'pm'}
assert set(Child.schema.fields.keys()) == {'id', 'cls', 'p', 'pm', 'c', 'cm'}

parent_data = {'p': 'parent', 'pm': 42}
child_data = {'c': 'Child', 'cm': 12, **parent_data}

with pytest.raises(ma.ValidationError) as exc:
Parent(**parent_data)
assert set(exc.value.messages.keys()) == {'pm'}
with pytest.raises(ma.ValidationError) as exc:
Child(**child_data)
assert set(exc.value.messages.keys()) == {'pm', 'cm'}


class TestConfig(BaseTest):

Expand Down
Loading