Format the codebase using Black (#2109)
This commit: 1. Formats all of our existing code using `black`. 2. Adds a note about using `black` to `CONTRIBUTING.rst`. 3. Runs `black --check` as part of CI (failing builds that aren't properly formatted).
This commit is contained in:
@@ -7,79 +7,78 @@ __all__ = ("QueryFieldListTest", "OnlyExcludeAllTest")
|
||||
|
||||
|
||||
class QueryFieldListTest(unittest.TestCase):
|
||||
|
||||
def test_empty(self):
|
||||
q = QueryFieldList()
|
||||
self.assertFalse(q)
|
||||
|
||||
q = QueryFieldList(always_include=['_cls'])
|
||||
q = QueryFieldList(always_include=["_cls"])
|
||||
self.assertFalse(q)
|
||||
|
||||
def test_include_include(self):
|
||||
q = QueryFieldList()
|
||||
q += QueryFieldList(fields=['a', 'b'], value=QueryFieldList.ONLY, _only_called=True)
|
||||
self.assertEqual(q.as_dict(), {'a': 1, 'b': 1})
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {'a': 1, 'b': 1, 'c': 1})
|
||||
q += QueryFieldList(
|
||||
fields=["a", "b"], value=QueryFieldList.ONLY, _only_called=True
|
||||
)
|
||||
self.assertEqual(q.as_dict(), {"a": 1, "b": 1})
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {"a": 1, "b": 1, "c": 1})
|
||||
|
||||
def test_include_exclude(self):
|
||||
q = QueryFieldList()
|
||||
q += QueryFieldList(fields=['a', 'b'], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {'a': 1, 'b': 1})
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {'a': 1})
|
||||
q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {"a": 1, "b": 1})
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {"a": 1})
|
||||
|
||||
def test_exclude_exclude(self):
|
||||
q = QueryFieldList()
|
||||
q += QueryFieldList(fields=['a', 'b'], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {'a': 0, 'b': 0})
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {'a': 0, 'b': 0, 'c': 0})
|
||||
q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {"a": 0, "b": 0})
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {"a": 0, "b": 0, "c": 0})
|
||||
|
||||
def test_exclude_include(self):
|
||||
q = QueryFieldList()
|
||||
q += QueryFieldList(fields=['a', 'b'], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {'a': 0, 'b': 0})
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {'c': 1})
|
||||
q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.EXCLUDE)
|
||||
self.assertEqual(q.as_dict(), {"a": 0, "b": 0})
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {"c": 1})
|
||||
|
||||
def test_always_include(self):
|
||||
q = QueryFieldList(always_include=['x', 'y'])
|
||||
q += QueryFieldList(fields=['a', 'b', 'x'], value=QueryFieldList.EXCLUDE)
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {'x': 1, 'y': 1, 'c': 1})
|
||||
q = QueryFieldList(always_include=["x", "y"])
|
||||
q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE)
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {"x": 1, "y": 1, "c": 1})
|
||||
|
||||
def test_reset(self):
|
||||
q = QueryFieldList(always_include=['x', 'y'])
|
||||
q += QueryFieldList(fields=['a', 'b', 'x'], value=QueryFieldList.EXCLUDE)
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {'x': 1, 'y': 1, 'c': 1})
|
||||
q = QueryFieldList(always_include=["x", "y"])
|
||||
q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE)
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {"x": 1, "y": 1, "c": 1})
|
||||
q.reset()
|
||||
self.assertFalse(q)
|
||||
q += QueryFieldList(fields=['b', 'c'], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {'x': 1, 'y': 1, 'b': 1, 'c': 1})
|
||||
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY)
|
||||
self.assertEqual(q.as_dict(), {"x": 1, "y": 1, "b": 1, "c": 1})
|
||||
|
||||
def test_using_a_slice(self):
|
||||
q = QueryFieldList()
|
||||
q += QueryFieldList(fields=['a'], value={"$slice": 5})
|
||||
self.assertEqual(q.as_dict(), {'a': {"$slice": 5}})
|
||||
q += QueryFieldList(fields=["a"], value={"$slice": 5})
|
||||
self.assertEqual(q.as_dict(), {"a": {"$slice": 5}})
|
||||
|
||||
|
||||
class OnlyExcludeAllTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
connect(db='mongoenginetest')
|
||||
connect(db="mongoenginetest")
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
age = IntField()
|
||||
meta = {'allow_inheritance': True}
|
||||
meta = {"allow_inheritance": True}
|
||||
|
||||
Person.drop_collection()
|
||||
self.Person = Person
|
||||
|
||||
def test_mixing_only_exclude(self):
|
||||
|
||||
class MyDoc(Document):
|
||||
a = StringField()
|
||||
b = StringField()
|
||||
@@ -88,32 +87,32 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
e = StringField()
|
||||
f = StringField()
|
||||
|
||||
include = ['a', 'b', 'c', 'd', 'e']
|
||||
exclude = ['d', 'e']
|
||||
only = ['b', 'c']
|
||||
include = ["a", "b", "c", "d", "e"]
|
||||
exclude = ["d", "e"]
|
||||
only = ["b", "c"]
|
||||
|
||||
qs = MyDoc.objects.fields(**{i: 1 for i in include})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||
{'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1})
|
||||
self.assertEqual(
|
||||
qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1, "d": 1, "e": 1}
|
||||
)
|
||||
qs = qs.only(*only)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {'b': 1, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1})
|
||||
qs = qs.exclude(*exclude)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {'b': 1, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1})
|
||||
|
||||
qs = MyDoc.objects.fields(**{i: 1 for i in include})
|
||||
qs = qs.exclude(*exclude)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {'a': 1, 'b': 1, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1})
|
||||
qs = qs.only(*only)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {'b': 1, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1})
|
||||
|
||||
qs = MyDoc.objects.exclude(*exclude)
|
||||
qs = qs.fields(**{i: 1 for i in include})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {'a': 1, 'b': 1, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1})
|
||||
qs = qs.only(*only)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {'b': 1, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1})
|
||||
|
||||
def test_slicing(self):
|
||||
|
||||
class MyDoc(Document):
|
||||
a = ListField()
|
||||
b = ListField()
|
||||
@@ -122,24 +121,23 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
e = ListField()
|
||||
f = ListField()
|
||||
|
||||
include = ['a', 'b', 'c', 'd', 'e']
|
||||
exclude = ['d', 'e']
|
||||
only = ['b', 'c']
|
||||
include = ["a", "b", "c", "d", "e"]
|
||||
exclude = ["d", "e"]
|
||||
only = ["b", "c"]
|
||||
|
||||
qs = MyDoc.objects.fields(**{i: 1 for i in include})
|
||||
qs = qs.exclude(*exclude)
|
||||
qs = qs.only(*only)
|
||||
qs = qs.fields(slice__b=5)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||
{'b': {'$slice': 5}, 'c': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"b": {"$slice": 5}, "c": 1})
|
||||
|
||||
qs = qs.fields(slice__c=[5, 1])
|
||||
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||
{'b': {'$slice': 5}, 'c': {'$slice': [5, 1]}})
|
||||
self.assertEqual(
|
||||
qs._loaded_fields.as_dict(), {"b": {"$slice": 5}, "c": {"$slice": [5, 1]}}
|
||||
)
|
||||
|
||||
qs = qs.exclude('c')
|
||||
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||
{'b': {'$slice': 5}})
|
||||
qs = qs.exclude("c")
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"b": {"$slice": 5}})
|
||||
|
||||
def test_mix_slice_with_other_fields(self):
|
||||
class MyDoc(Document):
|
||||
@@ -148,43 +146,42 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
c = ListField()
|
||||
|
||||
qs = MyDoc.objects.fields(a=1, b=0, slice__c=2)
|
||||
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||
{'c': {'$slice': 2}, 'a': 1})
|
||||
self.assertEqual(qs._loaded_fields.as_dict(), {"c": {"$slice": 2}, "a": 1})
|
||||
|
||||
def test_only(self):
|
||||
"""Ensure that QuerySet.only only returns the requested fields.
|
||||
"""
|
||||
person = self.Person(name='test', age=25)
|
||||
person = self.Person(name="test", age=25)
|
||||
person.save()
|
||||
|
||||
obj = self.Person.objects.only('name').get()
|
||||
obj = self.Person.objects.only("name").get()
|
||||
self.assertEqual(obj.name, person.name)
|
||||
self.assertEqual(obj.age, None)
|
||||
|
||||
obj = self.Person.objects.only('age').get()
|
||||
obj = self.Person.objects.only("age").get()
|
||||
self.assertEqual(obj.name, None)
|
||||
self.assertEqual(obj.age, person.age)
|
||||
|
||||
obj = self.Person.objects.only('name', 'age').get()
|
||||
obj = self.Person.objects.only("name", "age").get()
|
||||
self.assertEqual(obj.name, person.name)
|
||||
self.assertEqual(obj.age, person.age)
|
||||
|
||||
obj = self.Person.objects.only(*('id', 'name',)).get()
|
||||
obj = self.Person.objects.only(*("id", "name")).get()
|
||||
self.assertEqual(obj.name, person.name)
|
||||
self.assertEqual(obj.age, None)
|
||||
|
||||
# Check polymorphism still works
|
||||
class Employee(self.Person):
|
||||
salary = IntField(db_field='wage')
|
||||
salary = IntField(db_field="wage")
|
||||
|
||||
employee = Employee(name='test employee', age=40, salary=30000)
|
||||
employee = Employee(name="test employee", age=40, salary=30000)
|
||||
employee.save()
|
||||
|
||||
obj = self.Person.objects(id=employee.id).only('age').get()
|
||||
obj = self.Person.objects(id=employee.id).only("age").get()
|
||||
self.assertIsInstance(obj, Employee)
|
||||
|
||||
# Check field names are looked up properly
|
||||
obj = Employee.objects(id=employee.id).only('salary').get()
|
||||
obj = Employee.objects(id=employee.id).only("salary").get()
|
||||
self.assertEqual(obj.salary, employee.salary)
|
||||
self.assertEqual(obj.name, None)
|
||||
|
||||
@@ -208,35 +205,41 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
post = BlogPost(content='Had a good coffee today...', various={'test_dynamic': {'some': True}})
|
||||
post.author = User(name='Test User')
|
||||
post.comments = [Comment(title='I aggree', text='Great post!'), Comment(title='Coffee', text='I hate coffee')]
|
||||
post = BlogPost(
|
||||
content="Had a good coffee today...",
|
||||
various={"test_dynamic": {"some": True}},
|
||||
)
|
||||
post.author = User(name="Test User")
|
||||
post.comments = [
|
||||
Comment(title="I aggree", text="Great post!"),
|
||||
Comment(title="Coffee", text="I hate coffee"),
|
||||
]
|
||||
post.save()
|
||||
|
||||
obj = BlogPost.objects.only('author.name',).get()
|
||||
obj = BlogPost.objects.only("author.name").get()
|
||||
self.assertEqual(obj.content, None)
|
||||
self.assertEqual(obj.author.email, None)
|
||||
self.assertEqual(obj.author.name, 'Test User')
|
||||
self.assertEqual(obj.author.name, "Test User")
|
||||
self.assertEqual(obj.comments, [])
|
||||
|
||||
obj = BlogPost.objects.only('various.test_dynamic.some').get()
|
||||
obj = BlogPost.objects.only("various.test_dynamic.some").get()
|
||||
self.assertEqual(obj.various["test_dynamic"].some, True)
|
||||
|
||||
obj = BlogPost.objects.only('content', 'comments.title',).get()
|
||||
self.assertEqual(obj.content, 'Had a good coffee today...')
|
||||
obj = BlogPost.objects.only("content", "comments.title").get()
|
||||
self.assertEqual(obj.content, "Had a good coffee today...")
|
||||
self.assertEqual(obj.author, None)
|
||||
self.assertEqual(obj.comments[0].title, 'I aggree')
|
||||
self.assertEqual(obj.comments[1].title, 'Coffee')
|
||||
self.assertEqual(obj.comments[0].title, "I aggree")
|
||||
self.assertEqual(obj.comments[1].title, "Coffee")
|
||||
self.assertEqual(obj.comments[0].text, None)
|
||||
self.assertEqual(obj.comments[1].text, None)
|
||||
|
||||
obj = BlogPost.objects.only('comments',).get()
|
||||
obj = BlogPost.objects.only("comments").get()
|
||||
self.assertEqual(obj.content, None)
|
||||
self.assertEqual(obj.author, None)
|
||||
self.assertEqual(obj.comments[0].title, 'I aggree')
|
||||
self.assertEqual(obj.comments[1].title, 'Coffee')
|
||||
self.assertEqual(obj.comments[0].text, 'Great post!')
|
||||
self.assertEqual(obj.comments[1].text, 'I hate coffee')
|
||||
self.assertEqual(obj.comments[0].title, "I aggree")
|
||||
self.assertEqual(obj.comments[1].title, "Coffee")
|
||||
self.assertEqual(obj.comments[0].text, "Great post!")
|
||||
self.assertEqual(obj.comments[1].text, "I hate coffee")
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
@@ -256,15 +259,18 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
post = BlogPost(content='Had a good coffee today...')
|
||||
post.author = User(name='Test User')
|
||||
post.comments = [Comment(title='I aggree', text='Great post!'), Comment(title='Coffee', text='I hate coffee')]
|
||||
post = BlogPost(content="Had a good coffee today...")
|
||||
post.author = User(name="Test User")
|
||||
post.comments = [
|
||||
Comment(title="I aggree", text="Great post!"),
|
||||
Comment(title="Coffee", text="I hate coffee"),
|
||||
]
|
||||
post.save()
|
||||
|
||||
obj = BlogPost.objects.exclude('author', 'comments.text').get()
|
||||
obj = BlogPost.objects.exclude("author", "comments.text").get()
|
||||
self.assertEqual(obj.author, None)
|
||||
self.assertEqual(obj.content, 'Had a good coffee today...')
|
||||
self.assertEqual(obj.comments[0].title, 'I aggree')
|
||||
self.assertEqual(obj.content, "Had a good coffee today...")
|
||||
self.assertEqual(obj.comments[0].title, "I aggree")
|
||||
self.assertEqual(obj.comments[0].text, None)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
@@ -283,32 +289,43 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
attachments = ListField(EmbeddedDocumentField(Attachment))
|
||||
|
||||
Email.drop_collection()
|
||||
email = Email(sender='me', to='you', subject='From Russia with Love', body='Hello!', content_type='text/plain')
|
||||
email = Email(
|
||||
sender="me",
|
||||
to="you",
|
||||
subject="From Russia with Love",
|
||||
body="Hello!",
|
||||
content_type="text/plain",
|
||||
)
|
||||
email.attachments = [
|
||||
Attachment(name='file1.doc', content='ABC'),
|
||||
Attachment(name='file2.doc', content='XYZ'),
|
||||
Attachment(name="file1.doc", content="ABC"),
|
||||
Attachment(name="file2.doc", content="XYZ"),
|
||||
]
|
||||
email.save()
|
||||
|
||||
obj = Email.objects.exclude('content_type').exclude('body').get()
|
||||
self.assertEqual(obj.sender, 'me')
|
||||
self.assertEqual(obj.to, 'you')
|
||||
self.assertEqual(obj.subject, 'From Russia with Love')
|
||||
obj = Email.objects.exclude("content_type").exclude("body").get()
|
||||
self.assertEqual(obj.sender, "me")
|
||||
self.assertEqual(obj.to, "you")
|
||||
self.assertEqual(obj.subject, "From Russia with Love")
|
||||
self.assertEqual(obj.body, None)
|
||||
self.assertEqual(obj.content_type, None)
|
||||
|
||||
obj = Email.objects.only('sender', 'to').exclude('body', 'sender').get()
|
||||
obj = Email.objects.only("sender", "to").exclude("body", "sender").get()
|
||||
self.assertEqual(obj.sender, None)
|
||||
self.assertEqual(obj.to, 'you')
|
||||
self.assertEqual(obj.to, "you")
|
||||
self.assertEqual(obj.subject, None)
|
||||
self.assertEqual(obj.body, None)
|
||||
self.assertEqual(obj.content_type, None)
|
||||
|
||||
obj = Email.objects.exclude('attachments.content').exclude('body').only('to', 'attachments.name').get()
|
||||
self.assertEqual(obj.attachments[0].name, 'file1.doc')
|
||||
obj = (
|
||||
Email.objects.exclude("attachments.content")
|
||||
.exclude("body")
|
||||
.only("to", "attachments.name")
|
||||
.get()
|
||||
)
|
||||
self.assertEqual(obj.attachments[0].name, "file1.doc")
|
||||
self.assertEqual(obj.attachments[0].content, None)
|
||||
self.assertEqual(obj.sender, None)
|
||||
self.assertEqual(obj.to, 'you')
|
||||
self.assertEqual(obj.to, "you")
|
||||
self.assertEqual(obj.subject, None)
|
||||
self.assertEqual(obj.body, None)
|
||||
self.assertEqual(obj.content_type, None)
|
||||
@@ -316,7 +333,6 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
Email.drop_collection()
|
||||
|
||||
def test_all_fields(self):
|
||||
|
||||
class Email(Document):
|
||||
sender = StringField()
|
||||
to = StringField()
|
||||
@@ -326,21 +342,33 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
|
||||
Email.drop_collection()
|
||||
|
||||
email = Email(sender='me', to='you', subject='From Russia with Love', body='Hello!', content_type='text/plain')
|
||||
email = Email(
|
||||
sender="me",
|
||||
to="you",
|
||||
subject="From Russia with Love",
|
||||
body="Hello!",
|
||||
content_type="text/plain",
|
||||
)
|
||||
email.save()
|
||||
|
||||
obj = Email.objects.exclude('content_type', 'body').only('to', 'body').all_fields().get()
|
||||
self.assertEqual(obj.sender, 'me')
|
||||
self.assertEqual(obj.to, 'you')
|
||||
self.assertEqual(obj.subject, 'From Russia with Love')
|
||||
self.assertEqual(obj.body, 'Hello!')
|
||||
self.assertEqual(obj.content_type, 'text/plain')
|
||||
obj = (
|
||||
Email.objects.exclude("content_type", "body")
|
||||
.only("to", "body")
|
||||
.all_fields()
|
||||
.get()
|
||||
)
|
||||
self.assertEqual(obj.sender, "me")
|
||||
self.assertEqual(obj.to, "you")
|
||||
self.assertEqual(obj.subject, "From Russia with Love")
|
||||
self.assertEqual(obj.body, "Hello!")
|
||||
self.assertEqual(obj.content_type, "text/plain")
|
||||
|
||||
Email.drop_collection()
|
||||
|
||||
def test_slicing_fields(self):
|
||||
"""Ensure that query slicing an array works.
|
||||
"""
|
||||
|
||||
class Numbers(Document):
|
||||
n = ListField(IntField())
|
||||
|
||||
@@ -414,11 +442,10 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
self.assertEqual(numbers.embedded.n, [-5, -4, -3, -2, -1])
|
||||
|
||||
def test_exclude_from_subclasses_docs(self):
|
||||
|
||||
class Base(Document):
|
||||
username = StringField()
|
||||
|
||||
meta = {'allow_inheritance': True}
|
||||
meta = {"allow_inheritance": True}
|
||||
|
||||
class Anon(Base):
|
||||
anon = BooleanField()
|
||||
@@ -436,5 +463,5 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
self.assertRaises(LookUpError, Base.objects.exclude, "made_up")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -10,9 +10,9 @@ __all__ = ("GeoQueriesTest",)
|
||||
|
||||
|
||||
class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
def _create_event_data(self, point_field_class=GeoPointField):
|
||||
"""Create some sample data re-used in many of the tests below."""
|
||||
|
||||
class Event(Document):
|
||||
title = StringField()
|
||||
date = DateTimeField()
|
||||
@@ -28,15 +28,18 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
event1 = Event.objects.create(
|
||||
title="Coltrane Motion @ Double Door",
|
||||
date=datetime.datetime.now() - datetime.timedelta(days=1),
|
||||
location=[-87.677137, 41.909889])
|
||||
location=[-87.677137, 41.909889],
|
||||
)
|
||||
event2 = Event.objects.create(
|
||||
title="Coltrane Motion @ Bottom of the Hill",
|
||||
date=datetime.datetime.now() - datetime.timedelta(days=10),
|
||||
location=[-122.4194155, 37.7749295])
|
||||
location=[-122.4194155, 37.7749295],
|
||||
)
|
||||
event3 = Event.objects.create(
|
||||
title="Coltrane Motion @ Empty Bottle",
|
||||
date=datetime.datetime.now(),
|
||||
location=[-87.686638, 41.900474])
|
||||
location=[-87.686638, 41.900474],
|
||||
)
|
||||
|
||||
return event1, event2, event3
|
||||
|
||||
@@ -65,8 +68,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# find events within 10 degrees of san francisco
|
||||
point = [-122.415579, 37.7566023]
|
||||
events = self.Event.objects(location__near=point,
|
||||
location__max_distance=10)
|
||||
events = self.Event.objects(location__near=point, location__max_distance=10)
|
||||
self.assertEqual(events.count(), 1)
|
||||
self.assertEqual(events[0], event2)
|
||||
|
||||
@@ -78,8 +80,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# find events at least 10 degrees away of san francisco
|
||||
point = [-122.415579, 37.7566023]
|
||||
events = self.Event.objects(location__near=point,
|
||||
location__min_distance=10)
|
||||
events = self.Event.objects(location__near=point, location__min_distance=10)
|
||||
self.assertEqual(events.count(), 2)
|
||||
|
||||
def test_within_distance(self):
|
||||
@@ -88,8 +89,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# find events within 5 degrees of pitchfork office, chicago
|
||||
point_and_distance = [[-87.67892, 41.9120459], 5]
|
||||
events = self.Event.objects(
|
||||
location__within_distance=point_and_distance)
|
||||
events = self.Event.objects(location__within_distance=point_and_distance)
|
||||
self.assertEqual(events.count(), 2)
|
||||
events = list(events)
|
||||
self.assertNotIn(event2, events)
|
||||
@@ -98,21 +98,18 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# find events within 10 degrees of san francisco
|
||||
point_and_distance = [[-122.415579, 37.7566023], 10]
|
||||
events = self.Event.objects(
|
||||
location__within_distance=point_and_distance)
|
||||
events = self.Event.objects(location__within_distance=point_and_distance)
|
||||
self.assertEqual(events.count(), 1)
|
||||
self.assertEqual(events[0], event2)
|
||||
|
||||
# find events within 1 degree of greenpoint, broolyn, nyc, ny
|
||||
point_and_distance = [[-73.9509714, 40.7237134], 1]
|
||||
events = self.Event.objects(
|
||||
location__within_distance=point_and_distance)
|
||||
events = self.Event.objects(location__within_distance=point_and_distance)
|
||||
self.assertEqual(events.count(), 0)
|
||||
|
||||
# ensure ordering is respected by "within_distance"
|
||||
point_and_distance = [[-87.67892, 41.9120459], 10]
|
||||
events = self.Event.objects(
|
||||
location__within_distance=point_and_distance)
|
||||
events = self.Event.objects(location__within_distance=point_and_distance)
|
||||
events = events.order_by("-date")
|
||||
self.assertEqual(events.count(), 2)
|
||||
self.assertEqual(events[0], event3)
|
||||
@@ -145,7 +142,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
polygon2 = [
|
||||
(-1.742249, 54.033586),
|
||||
(-1.225891, 52.792797),
|
||||
(-4.40094, 53.389881)
|
||||
(-4.40094, 53.389881),
|
||||
]
|
||||
events = self.Event.objects(location__within_polygon=polygon2)
|
||||
self.assertEqual(events.count(), 0)
|
||||
@@ -154,9 +151,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Make sure the "near" operator works with a PointField, which
|
||||
corresponds to a 2dsphere index.
|
||||
"""
|
||||
event1, event2, event3 = self._create_event_data(
|
||||
point_field_class=PointField
|
||||
)
|
||||
event1, event2, event3 = self._create_event_data(point_field_class=PointField)
|
||||
|
||||
# find all events "near" pitchfork office, chicago.
|
||||
# note that "near" will show the san francisco event, too,
|
||||
@@ -175,26 +170,23 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Ensure the "max_distance" operator works alongside the "near"
|
||||
operator with a 2dsphere index.
|
||||
"""
|
||||
event1, event2, event3 = self._create_event_data(
|
||||
point_field_class=PointField
|
||||
)
|
||||
event1, event2, event3 = self._create_event_data(point_field_class=PointField)
|
||||
|
||||
# find events within 10km of san francisco
|
||||
point = [-122.415579, 37.7566023]
|
||||
events = self.Event.objects(location__near=point,
|
||||
location__max_distance=10000)
|
||||
events = self.Event.objects(location__near=point, location__max_distance=10000)
|
||||
self.assertEqual(events.count(), 1)
|
||||
self.assertEqual(events[0], event2)
|
||||
|
||||
# find events within 1km of greenpoint, broolyn, nyc, ny
|
||||
events = self.Event.objects(location__near=[-73.9509714, 40.7237134],
|
||||
location__max_distance=1000)
|
||||
events = self.Event.objects(
|
||||
location__near=[-73.9509714, 40.7237134], location__max_distance=1000
|
||||
)
|
||||
self.assertEqual(events.count(), 0)
|
||||
|
||||
# ensure ordering is respected by "near"
|
||||
events = self.Event.objects(
|
||||
location__near=[-87.67892, 41.9120459],
|
||||
location__max_distance=10000
|
||||
location__near=[-87.67892, 41.9120459], location__max_distance=10000
|
||||
).order_by("-date")
|
||||
self.assertEqual(events.count(), 2)
|
||||
self.assertEqual(events[0], event3)
|
||||
@@ -203,9 +195,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Ensure the "geo_within_box" operator works with a 2dsphere
|
||||
index.
|
||||
"""
|
||||
event1, event2, event3 = self._create_event_data(
|
||||
point_field_class=PointField
|
||||
)
|
||||
event1, event2, event3 = self._create_event_data(point_field_class=PointField)
|
||||
|
||||
# check that within_box works
|
||||
box = [(-125.0, 35.0), (-100.0, 40.0)]
|
||||
@@ -217,9 +207,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Ensure the "geo_within_polygon" operator works with a
|
||||
2dsphere index.
|
||||
"""
|
||||
event1, event2, event3 = self._create_event_data(
|
||||
point_field_class=PointField
|
||||
)
|
||||
event1, event2, event3 = self._create_event_data(point_field_class=PointField)
|
||||
|
||||
polygon = [
|
||||
(-87.694445, 41.912114),
|
||||
@@ -235,7 +223,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
polygon2 = [
|
||||
(-1.742249, 54.033586),
|
||||
(-1.225891, 52.792797),
|
||||
(-4.40094, 53.389881)
|
||||
(-4.40094, 53.389881),
|
||||
]
|
||||
events = self.Event.objects(location__geo_within_polygon=polygon2)
|
||||
self.assertEqual(events.count(), 0)
|
||||
@@ -244,23 +232,20 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Ensure "min_distace" and "max_distance" operators work well
|
||||
together with the "near" operator in a 2dsphere index.
|
||||
"""
|
||||
event1, event2, event3 = self._create_event_data(
|
||||
point_field_class=PointField
|
||||
)
|
||||
event1, event2, event3 = self._create_event_data(point_field_class=PointField)
|
||||
|
||||
# ensure min_distance and max_distance combine well
|
||||
events = self.Event.objects(
|
||||
location__near=[-87.67892, 41.9120459],
|
||||
location__min_distance=1000,
|
||||
location__max_distance=10000
|
||||
location__max_distance=10000,
|
||||
).order_by("-date")
|
||||
self.assertEqual(events.count(), 1)
|
||||
self.assertEqual(events[0], event3)
|
||||
|
||||
# ensure ordering is respected by "near" with "min_distance"
|
||||
events = self.Event.objects(
|
||||
location__near=[-87.67892, 41.9120459],
|
||||
location__min_distance=10000
|
||||
location__near=[-87.67892, 41.9120459], location__min_distance=10000
|
||||
).order_by("-date")
|
||||
self.assertEqual(events.count(), 1)
|
||||
self.assertEqual(events[0], event2)
|
||||
@@ -269,14 +254,11 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Make sure the "geo_within_center" operator works with a
|
||||
2dsphere index.
|
||||
"""
|
||||
event1, event2, event3 = self._create_event_data(
|
||||
point_field_class=PointField
|
||||
)
|
||||
event1, event2, event3 = self._create_event_data(point_field_class=PointField)
|
||||
|
||||
# find events within 5 degrees of pitchfork office, chicago
|
||||
point_and_distance = [[-87.67892, 41.9120459], 2]
|
||||
events = self.Event.objects(
|
||||
location__geo_within_center=point_and_distance)
|
||||
events = self.Event.objects(location__geo_within_center=point_and_distance)
|
||||
self.assertEqual(events.count(), 2)
|
||||
events = list(events)
|
||||
self.assertNotIn(event2, events)
|
||||
@@ -287,6 +269,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
"""Helper test method ensuring given point field class works
|
||||
well in an embedded document.
|
||||
"""
|
||||
|
||||
class Venue(EmbeddedDocument):
|
||||
location = point_field_class()
|
||||
name = StringField()
|
||||
@@ -300,12 +283,11 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
venue1 = Venue(name="The Rock", location=[-87.677137, 41.909889])
|
||||
venue2 = Venue(name="The Bridge", location=[-122.4194155, 37.7749295])
|
||||
|
||||
event1 = Event(title="Coltrane Motion @ Double Door",
|
||||
venue=venue1).save()
|
||||
event2 = Event(title="Coltrane Motion @ Bottom of the Hill",
|
||||
venue=venue2).save()
|
||||
event3 = Event(title="Coltrane Motion @ Empty Bottle",
|
||||
venue=venue1).save()
|
||||
event1 = Event(title="Coltrane Motion @ Double Door", venue=venue1).save()
|
||||
event2 = Event(
|
||||
title="Coltrane Motion @ Bottom of the Hill", venue=venue2
|
||||
).save()
|
||||
event3 = Event(title="Coltrane Motion @ Empty Bottle", venue=venue1).save()
|
||||
|
||||
# find all events "near" pitchfork office, chicago.
|
||||
# note that "near" will show the san francisco event, too,
|
||||
@@ -324,6 +306,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
def test_spherical_geospatial_operators(self):
|
||||
"""Ensure that spherical geospatial queries are working."""
|
||||
|
||||
class Point(Document):
|
||||
location = GeoPointField()
|
||||
|
||||
@@ -343,26 +326,26 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# Same behavior for _within_spherical_distance
|
||||
points = Point.objects(
|
||||
location__within_spherical_distance=[
|
||||
[-122, 37.5],
|
||||
60 / earth_radius
|
||||
]
|
||||
location__within_spherical_distance=[[-122, 37.5], 60 / earth_radius]
|
||||
)
|
||||
self.assertEqual(points.count(), 2)
|
||||
|
||||
points = Point.objects(location__near_sphere=[-122, 37.5],
|
||||
location__max_distance=60 / earth_radius)
|
||||
points = Point.objects(
|
||||
location__near_sphere=[-122, 37.5], location__max_distance=60 / earth_radius
|
||||
)
|
||||
self.assertEqual(points.count(), 2)
|
||||
|
||||
# Test query works with max_distance, being farer from one point
|
||||
points = Point.objects(location__near_sphere=[-122, 37.8],
|
||||
location__max_distance=60 / earth_radius)
|
||||
points = Point.objects(
|
||||
location__near_sphere=[-122, 37.8], location__max_distance=60 / earth_radius
|
||||
)
|
||||
close_point = points.first()
|
||||
self.assertEqual(points.count(), 1)
|
||||
|
||||
# Test query works with min_distance, being farer from one point
|
||||
points = Point.objects(location__near_sphere=[-122, 37.8],
|
||||
location__min_distance=60 / earth_radius)
|
||||
points = Point.objects(
|
||||
location__near_sphere=[-122, 37.8], location__min_distance=60 / earth_radius
|
||||
)
|
||||
self.assertEqual(points.count(), 1)
|
||||
far_point = points.first()
|
||||
self.assertNotEqual(close_point, far_point)
|
||||
@@ -384,10 +367,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
# Finds only one point because only the first point is within 60km of
|
||||
# the reference point to the south.
|
||||
points = Point.objects(
|
||||
location__within_spherical_distance=[
|
||||
[-122, 36.5],
|
||||
60 / earth_radius
|
||||
]
|
||||
location__within_spherical_distance=[[-122, 36.5], 60 / earth_radius]
|
||||
)
|
||||
self.assertEqual(points.count(), 1)
|
||||
self.assertEqual(points[0].id, south_point.id)
|
||||
@@ -413,8 +393,10 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
# Within
|
||||
polygon = {"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]}
|
||||
polygon = {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
|
||||
}
|
||||
roads = Road.objects.filter(line__geo_within=polygon["coordinates"]).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
@@ -425,8 +407,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
# Intersects
|
||||
line = {"type": "LineString",
|
||||
"coordinates": [[40, 5], [40, 6]]}
|
||||
line = {"type": "LineString", "coordinates": [[40, 5], [40, 6]]}
|
||||
roads = Road.objects.filter(line__geo_intersects=line["coordinates"]).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
@@ -436,8 +417,10 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
roads = Road.objects.filter(line__geo_intersects={"$geometry": line}).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
polygon = {"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]}
|
||||
polygon = {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
|
||||
}
|
||||
roads = Road.objects.filter(line__geo_intersects=polygon["coordinates"]).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
@@ -468,8 +451,10 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
# Within
|
||||
polygon = {"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]}
|
||||
polygon = {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
|
||||
}
|
||||
roads = Road.objects.filter(poly__geo_within=polygon["coordinates"]).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
@@ -480,8 +465,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
# Intersects
|
||||
line = {"type": "LineString",
|
||||
"coordinates": [[40, 5], [41, 6]]}
|
||||
line = {"type": "LineString", "coordinates": [[40, 5], [41, 6]]}
|
||||
roads = Road.objects.filter(poly__geo_intersects=line["coordinates"]).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
@@ -491,8 +475,10 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
roads = Road.objects.filter(poly__geo_intersects={"$geometry": line}).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
polygon = {"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]}
|
||||
polygon = {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
|
||||
}
|
||||
roads = Road.objects.filter(poly__geo_intersects=polygon["coordinates"]).count()
|
||||
self.assertEqual(1, roads)
|
||||
|
||||
@@ -504,20 +490,20 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
def test_aspymongo_with_only(self):
|
||||
"""Ensure as_pymongo works with only"""
|
||||
|
||||
class Place(Document):
|
||||
location = PointField()
|
||||
|
||||
Place.drop_collection()
|
||||
p = Place(location=[24.946861267089844, 60.16311983618494])
|
||||
p.save()
|
||||
qs = Place.objects().only('location')
|
||||
qs = Place.objects().only("location")
|
||||
self.assertDictEqual(
|
||||
qs.as_pymongo()[0]['location'],
|
||||
{u'type': u'Point',
|
||||
u'coordinates': [
|
||||
24.946861267089844,
|
||||
60.16311983618494]
|
||||
}
|
||||
qs.as_pymongo()[0]["location"],
|
||||
{
|
||||
u"type": u"Point",
|
||||
u"coordinates": [24.946861267089844, 60.16311983618494],
|
||||
},
|
||||
)
|
||||
|
||||
def test_2dsphere_point_sets_correctly(self):
|
||||
@@ -542,11 +528,15 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
Location(line=[[1, 2], [2, 2]]).save()
|
||||
loc = Location.objects.as_pymongo()[0]
|
||||
self.assertEqual(loc["line"], {"type": "LineString", "coordinates": [[1, 2], [2, 2]]})
|
||||
self.assertEqual(
|
||||
loc["line"], {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}
|
||||
)
|
||||
|
||||
Location.objects.update(set__line=[[2, 1], [1, 2]])
|
||||
loc = Location.objects.as_pymongo()[0]
|
||||
self.assertEqual(loc["line"], {"type": "LineString", "coordinates": [[2, 1], [1, 2]]})
|
||||
self.assertEqual(
|
||||
loc["line"], {"type": "LineString", "coordinates": [[2, 1], [1, 2]]}
|
||||
)
|
||||
|
||||
def test_geojson_PolygonField(self):
|
||||
class Location(Document):
|
||||
@@ -556,12 +546,18 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
Location(poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]]).save()
|
||||
loc = Location.objects.as_pymongo()[0]
|
||||
self.assertEqual(loc["poly"], {"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]})
|
||||
self.assertEqual(
|
||||
loc["poly"],
|
||||
{"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]},
|
||||
)
|
||||
|
||||
Location.objects.update(set__poly=[[[40, 4], [40, 6], [41, 6], [40, 4]]])
|
||||
loc = Location.objects.as_pymongo()[0]
|
||||
self.assertEqual(loc["poly"], {"type": "Polygon", "coordinates": [[[40, 4], [40, 6], [41, 6], [40, 4]]]})
|
||||
self.assertEqual(
|
||||
loc["poly"],
|
||||
{"type": "Polygon", "coordinates": [[[40, 4], [40, 6], [41, 6], [40, 4]]]},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -11,7 +11,6 @@ class Doc(Document):
|
||||
|
||||
|
||||
class FindAndModifyTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
connect(db="mongoenginetest")
|
||||
Doc.drop_collection()
|
||||
@@ -82,9 +81,14 @@ class FindAndModifyTest(unittest.TestCase):
|
||||
|
||||
old_doc = Doc.objects().order_by("-id").modify(set__value=-1)
|
||||
self.assertEqual(old_doc.to_json(), doc.to_json())
|
||||
self.assertDbEqual([
|
||||
{"_id": 0, "value": 3}, {"_id": 1, "value": 2},
|
||||
{"_id": 2, "value": 1}, {"_id": 3, "value": -1}])
|
||||
self.assertDbEqual(
|
||||
[
|
||||
{"_id": 0, "value": 3},
|
||||
{"_id": 1, "value": 2},
|
||||
{"_id": 2, "value": 1},
|
||||
{"_id": 3, "value": -1},
|
||||
]
|
||||
)
|
||||
|
||||
def test_modify_with_fields(self):
|
||||
Doc(id=0, value=0).save()
|
||||
@@ -103,27 +107,25 @@ class FindAndModifyTest(unittest.TestCase):
|
||||
blog = BlogPost.objects.create()
|
||||
|
||||
# Push a new tag via modify with new=False (default).
|
||||
BlogPost(id=blog.id).modify(push__tags='code')
|
||||
BlogPost(id=blog.id).modify(push__tags="code")
|
||||
self.assertEqual(blog.tags, [])
|
||||
blog.reload()
|
||||
self.assertEqual(blog.tags, ['code'])
|
||||
self.assertEqual(blog.tags, ["code"])
|
||||
|
||||
# Push a new tag via modify with new=True.
|
||||
blog = BlogPost.objects(id=blog.id).modify(push__tags='java', new=True)
|
||||
self.assertEqual(blog.tags, ['code', 'java'])
|
||||
blog = BlogPost.objects(id=blog.id).modify(push__tags="java", new=True)
|
||||
self.assertEqual(blog.tags, ["code", "java"])
|
||||
|
||||
# Push a new tag with a positional argument.
|
||||
blog = BlogPost.objects(id=blog.id).modify(
|
||||
push__tags__0='python',
|
||||
new=True)
|
||||
self.assertEqual(blog.tags, ['python', 'code', 'java'])
|
||||
blog = BlogPost.objects(id=blog.id).modify(push__tags__0="python", new=True)
|
||||
self.assertEqual(blog.tags, ["python", "code", "java"])
|
||||
|
||||
# Push multiple new tags with a positional argument.
|
||||
blog = BlogPost.objects(id=blog.id).modify(
|
||||
push__tags__1=['go', 'rust'],
|
||||
new=True)
|
||||
self.assertEqual(blog.tags, ['python', 'go', 'rust', 'code', 'java'])
|
||||
push__tags__1=["go", "rust"], new=True
|
||||
)
|
||||
self.assertEqual(blog.tags, ["python", "go", "rust", "code", "java"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -4,7 +4,7 @@ from pymongo.mongo_client import MongoClient
|
||||
from mongoengine import Document, StringField, IntField
|
||||
from mongoengine.connection import connect
|
||||
|
||||
__author__ = 'stas'
|
||||
__author__ = "stas"
|
||||
|
||||
|
||||
class Person(Document):
|
||||
@@ -17,6 +17,7 @@ class TestQuerysetPickable(unittest.TestCase):
|
||||
Test for adding pickling support for QuerySet instances
|
||||
See issue https://github.com/MongoEngine/mongoengine/issues/442
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestQuerysetPickable, self).setUp()
|
||||
|
||||
@@ -24,10 +25,7 @@ class TestQuerysetPickable(unittest.TestCase):
|
||||
|
||||
connection.drop_database("test")
|
||||
|
||||
self.john = Person.objects.create(
|
||||
name="John",
|
||||
age=21
|
||||
)
|
||||
self.john = Person.objects.create(name="John", age=21)
|
||||
|
||||
def test_picke_simple_qs(self):
|
||||
|
||||
@@ -54,15 +52,9 @@ class TestQuerysetPickable(unittest.TestCase):
|
||||
self.assertEqual(Person.objects.first().age, 23)
|
||||
|
||||
def test_pickle_support_filtration(self):
|
||||
Person.objects.create(
|
||||
name="Alice",
|
||||
age=22
|
||||
)
|
||||
Person.objects.create(name="Alice", age=22)
|
||||
|
||||
Person.objects.create(
|
||||
name="Bob",
|
||||
age=23
|
||||
)
|
||||
Person.objects.create(name="Bob", age=23)
|
||||
|
||||
qs = Person.objects.filter(age__gte=22)
|
||||
self.assertEqual(qs.count(), 2)
|
||||
@@ -71,9 +63,3 @@ class TestQuerysetPickable(unittest.TestCase):
|
||||
|
||||
self.assertEqual(loaded.count(), 2)
|
||||
self.assertEqual(loaded.filter(name="Bob").first().age, 23)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,25 +9,29 @@ __all__ = ("TransformTest",)
|
||||
|
||||
|
||||
class TransformTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
connect(db='mongoenginetest')
|
||||
connect(db="mongoenginetest")
|
||||
|
||||
def test_transform_query(self):
|
||||
"""Ensure that the _transform_query function operates correctly.
|
||||
"""
|
||||
self.assertEqual(transform.query(name='test', age=30),
|
||||
{'name': 'test', 'age': 30})
|
||||
self.assertEqual(transform.query(age__lt=30),
|
||||
{'age': {'$lt': 30}})
|
||||
self.assertEqual(transform.query(age__gt=20, age__lt=50),
|
||||
{'age': {'$gt': 20, '$lt': 50}})
|
||||
self.assertEqual(transform.query(age=20, age__gt=50),
|
||||
{'$and': [{'age': {'$gt': 50}}, {'age': 20}]})
|
||||
self.assertEqual(transform.query(friend__age__gte=30),
|
||||
{'friend.age': {'$gte': 30}})
|
||||
self.assertEqual(transform.query(name__exists=True),
|
||||
{'name': {'$exists': True}})
|
||||
self.assertEqual(
|
||||
transform.query(name="test", age=30), {"name": "test", "age": 30}
|
||||
)
|
||||
self.assertEqual(transform.query(age__lt=30), {"age": {"$lt": 30}})
|
||||
self.assertEqual(
|
||||
transform.query(age__gt=20, age__lt=50), {"age": {"$gt": 20, "$lt": 50}}
|
||||
)
|
||||
self.assertEqual(
|
||||
transform.query(age=20, age__gt=50),
|
||||
{"$and": [{"age": {"$gt": 50}}, {"age": 20}]},
|
||||
)
|
||||
self.assertEqual(
|
||||
transform.query(friend__age__gte=30), {"friend.age": {"$gte": 30}}
|
||||
)
|
||||
self.assertEqual(
|
||||
transform.query(name__exists=True), {"name": {"$exists": True}}
|
||||
)
|
||||
|
||||
def test_transform_update(self):
|
||||
class LisDoc(Document):
|
||||
@@ -46,7 +50,11 @@ class TransformTest(unittest.TestCase):
|
||||
DicDoc().save()
|
||||
doc = Doc().save()
|
||||
|
||||
for k, v in (("set", "$set"), ("set_on_insert", "$setOnInsert"), ("push", "$push")):
|
||||
for k, v in (
|
||||
("set", "$set"),
|
||||
("set_on_insert", "$setOnInsert"),
|
||||
("push", "$push"),
|
||||
):
|
||||
update = transform.update(DicDoc, **{"%s__dictField__test" % k: doc})
|
||||
self.assertIsInstance(update[v]["dictField.test"], dict)
|
||||
|
||||
@@ -57,55 +65,61 @@ class TransformTest(unittest.TestCase):
|
||||
update = transform.update(DicDoc, pull__dictField__test=doc)
|
||||
self.assertIsInstance(update["$pull"]["dictField"]["test"], dict)
|
||||
|
||||
update = transform.update(LisDoc, pull__foo__in=['a'])
|
||||
self.assertEqual(update, {'$pull': {'foo': {'$in': ['a']}}})
|
||||
update = transform.update(LisDoc, pull__foo__in=["a"])
|
||||
self.assertEqual(update, {"$pull": {"foo": {"$in": ["a"]}}})
|
||||
|
||||
def test_transform_update_push(self):
|
||||
"""Ensure the differences in behvaior between 'push' and 'push_all'"""
|
||||
|
||||
class BlogPost(Document):
|
||||
tags = ListField(StringField())
|
||||
|
||||
update = transform.update(BlogPost, push__tags=['mongo', 'db'])
|
||||
self.assertEqual(update, {'$push': {'tags': ['mongo', 'db']}})
|
||||
update = transform.update(BlogPost, push__tags=["mongo", "db"])
|
||||
self.assertEqual(update, {"$push": {"tags": ["mongo", "db"]}})
|
||||
|
||||
update = transform.update(BlogPost, push_all__tags=['mongo', 'db'])
|
||||
self.assertEqual(update, {'$push': {'tags': {'$each': ['mongo', 'db']}}})
|
||||
update = transform.update(BlogPost, push_all__tags=["mongo", "db"])
|
||||
self.assertEqual(update, {"$push": {"tags": {"$each": ["mongo", "db"]}}})
|
||||
|
||||
def test_transform_update_no_operator_default_to_set(self):
|
||||
"""Ensure the differences in behvaior between 'push' and 'push_all'"""
|
||||
|
||||
class BlogPost(Document):
|
||||
tags = ListField(StringField())
|
||||
|
||||
update = transform.update(BlogPost, tags=['mongo', 'db'])
|
||||
self.assertEqual(update, {'$set': {'tags': ['mongo', 'db']}})
|
||||
update = transform.update(BlogPost, tags=["mongo", "db"])
|
||||
self.assertEqual(update, {"$set": {"tags": ["mongo", "db"]}})
|
||||
|
||||
def test_query_field_name(self):
|
||||
"""Ensure that the correct field name is used when querying.
|
||||
"""
|
||||
|
||||
class Comment(EmbeddedDocument):
|
||||
content = StringField(db_field='commentContent')
|
||||
content = StringField(db_field="commentContent")
|
||||
|
||||
class BlogPost(Document):
|
||||
title = StringField(db_field='postTitle')
|
||||
comments = ListField(EmbeddedDocumentField(Comment),
|
||||
db_field='postComments')
|
||||
title = StringField(db_field="postTitle")
|
||||
comments = ListField(
|
||||
EmbeddedDocumentField(Comment), db_field="postComments"
|
||||
)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
data = {'title': 'Post 1', 'comments': [Comment(content='test')]}
|
||||
data = {"title": "Post 1", "comments": [Comment(content="test")]}
|
||||
post = BlogPost(**data)
|
||||
post.save()
|
||||
|
||||
self.assertIn('postTitle', BlogPost.objects(title=data['title'])._query)
|
||||
self.assertFalse('title' in
|
||||
BlogPost.objects(title=data['title'])._query)
|
||||
self.assertEqual(BlogPost.objects(title=data['title']).count(), 1)
|
||||
self.assertIn("postTitle", BlogPost.objects(title=data["title"])._query)
|
||||
self.assertFalse("title" in BlogPost.objects(title=data["title"])._query)
|
||||
self.assertEqual(BlogPost.objects(title=data["title"]).count(), 1)
|
||||
|
||||
self.assertIn('_id', BlogPost.objects(pk=post.id)._query)
|
||||
self.assertIn("_id", BlogPost.objects(pk=post.id)._query)
|
||||
self.assertEqual(BlogPost.objects(pk=post.id).count(), 1)
|
||||
|
||||
self.assertIn('postComments.commentContent', BlogPost.objects(comments__content='test')._query)
|
||||
self.assertEqual(BlogPost.objects(comments__content='test').count(), 1)
|
||||
self.assertIn(
|
||||
"postComments.commentContent",
|
||||
BlogPost.objects(comments__content="test")._query,
|
||||
)
|
||||
self.assertEqual(BlogPost.objects(comments__content="test").count(), 1)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
@@ -113,18 +127,19 @@ class TransformTest(unittest.TestCase):
|
||||
"""Ensure that the correct "primary key" field name is used when
|
||||
querying
|
||||
"""
|
||||
|
||||
class BlogPost(Document):
|
||||
title = StringField(primary_key=True, db_field='postTitle')
|
||||
title = StringField(primary_key=True, db_field="postTitle")
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
data = {'title': 'Post 1'}
|
||||
data = {"title": "Post 1"}
|
||||
post = BlogPost(**data)
|
||||
post.save()
|
||||
|
||||
self.assertIn('_id', BlogPost.objects(pk=data['title'])._query)
|
||||
self.assertIn('_id', BlogPost.objects(title=data['title'])._query)
|
||||
self.assertEqual(BlogPost.objects(pk=data['title']).count(), 1)
|
||||
self.assertIn("_id", BlogPost.objects(pk=data["title"])._query)
|
||||
self.assertIn("_id", BlogPost.objects(title=data["title"])._query)
|
||||
self.assertEqual(BlogPost.objects(pk=data["title"]).count(), 1)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
@@ -156,78 +171,125 @@ class TransformTest(unittest.TestCase):
|
||||
"""
|
||||
Test raw plays nicely
|
||||
"""
|
||||
|
||||
class Foo(Document):
|
||||
name = StringField()
|
||||
a = StringField()
|
||||
b = StringField()
|
||||
c = StringField()
|
||||
|
||||
meta = {
|
||||
'allow_inheritance': False
|
||||
}
|
||||
meta = {"allow_inheritance": False}
|
||||
|
||||
query = Foo.objects(__raw__={'$nor': [{'name': 'bar'}]})._query
|
||||
self.assertEqual(query, {'$nor': [{'name': 'bar'}]})
|
||||
query = Foo.objects(__raw__={"$nor": [{"name": "bar"}]})._query
|
||||
self.assertEqual(query, {"$nor": [{"name": "bar"}]})
|
||||
|
||||
q1 = {'$or': [{'a': 1}, {'b': 1}]}
|
||||
q1 = {"$or": [{"a": 1}, {"b": 1}]}
|
||||
query = Foo.objects(Q(__raw__=q1) & Q(c=1))._query
|
||||
self.assertEqual(query, {'$or': [{'a': 1}, {'b': 1}], 'c': 1})
|
||||
self.assertEqual(query, {"$or": [{"a": 1}, {"b": 1}], "c": 1})
|
||||
|
||||
def test_raw_and_merging(self):
|
||||
class Doc(Document):
|
||||
meta = {'allow_inheritance': False}
|
||||
meta = {"allow_inheritance": False}
|
||||
|
||||
raw_query = Doc.objects(__raw__={
|
||||
'deleted': False,
|
||||
'scraped': 'yes',
|
||||
'$nor': [
|
||||
{'views.extracted': 'no'},
|
||||
{'attachments.views.extracted': 'no'}
|
||||
]
|
||||
})._query
|
||||
raw_query = Doc.objects(
|
||||
__raw__={
|
||||
"deleted": False,
|
||||
"scraped": "yes",
|
||||
"$nor": [
|
||||
{"views.extracted": "no"},
|
||||
{"attachments.views.extracted": "no"},
|
||||
],
|
||||
}
|
||||
)._query
|
||||
|
||||
self.assertEqual(raw_query, {
|
||||
'deleted': False,
|
||||
'scraped': 'yes',
|
||||
'$nor': [
|
||||
{'views.extracted': 'no'},
|
||||
{'attachments.views.extracted': 'no'}
|
||||
]
|
||||
})
|
||||
self.assertEqual(
|
||||
raw_query,
|
||||
{
|
||||
"deleted": False,
|
||||
"scraped": "yes",
|
||||
"$nor": [
|
||||
{"views.extracted": "no"},
|
||||
{"attachments.views.extracted": "no"},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
def test_geojson_PointField(self):
|
||||
class Location(Document):
|
||||
loc = PointField()
|
||||
|
||||
update = transform.update(Location, set__loc=[1, 2])
|
||||
self.assertEqual(update, {'$set': {'loc': {"type": "Point", "coordinates": [1, 2]}}})
|
||||
self.assertEqual(
|
||||
update, {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}}
|
||||
)
|
||||
|
||||
update = transform.update(Location, set__loc={"type": "Point", "coordinates": [1, 2]})
|
||||
self.assertEqual(update, {'$set': {'loc': {"type": "Point", "coordinates": [1, 2]}}})
|
||||
update = transform.update(
|
||||
Location, set__loc={"type": "Point", "coordinates": [1, 2]}
|
||||
)
|
||||
self.assertEqual(
|
||||
update, {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}}
|
||||
)
|
||||
|
||||
def test_geojson_LineStringField(self):
|
||||
class Location(Document):
|
||||
line = LineStringField()
|
||||
|
||||
update = transform.update(Location, set__line=[[1, 2], [2, 2]])
|
||||
self.assertEqual(update, {'$set': {'line': {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}})
|
||||
self.assertEqual(
|
||||
update,
|
||||
{"$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}},
|
||||
)
|
||||
|
||||
update = transform.update(Location, set__line={"type": "LineString", "coordinates": [[1, 2], [2, 2]]})
|
||||
self.assertEqual(update, {'$set': {'line': {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}})
|
||||
update = transform.update(
|
||||
Location, set__line={"type": "LineString", "coordinates": [[1, 2], [2, 2]]}
|
||||
)
|
||||
self.assertEqual(
|
||||
update,
|
||||
{"$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}},
|
||||
)
|
||||
|
||||
def test_geojson_PolygonField(self):
|
||||
class Location(Document):
|
||||
poly = PolygonField()
|
||||
|
||||
update = transform.update(Location, set__poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]])
|
||||
self.assertEqual(update, {'$set': {'poly': {"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]}}})
|
||||
update = transform.update(
|
||||
Location, set__poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]]
|
||||
)
|
||||
self.assertEqual(
|
||||
update,
|
||||
{
|
||||
"$set": {
|
||||
"poly": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
update = transform.update(Location, set__poly={"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]})
|
||||
self.assertEqual(update, {'$set': {'poly': {"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]}}})
|
||||
update = transform.update(
|
||||
Location,
|
||||
set__poly={
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
update,
|
||||
{
|
||||
"$set": {
|
||||
"poly": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
def test_type(self):
|
||||
class Doc(Document):
|
||||
df = DynamicField()
|
||||
|
||||
Doc(df=True).save()
|
||||
Doc(df=7).save()
|
||||
Doc(df="df").save()
|
||||
@@ -252,7 +314,7 @@ class TransformTest(unittest.TestCase):
|
||||
self.assertEqual(1, Doc.objects(item__type__="axe").count())
|
||||
self.assertEqual(1, Doc.objects(item__name__="Heroic axe").count())
|
||||
|
||||
Doc.objects(id=doc.id).update(set__item__type__='sword')
|
||||
Doc.objects(id=doc.id).update(set__item__type__="sword")
|
||||
self.assertEqual(1, Doc.objects(item__type__="sword").count())
|
||||
self.assertEqual(0, Doc.objects(item__type__="axe").count())
|
||||
|
||||
@@ -272,6 +334,7 @@ class TransformTest(unittest.TestCase):
|
||||
Test added to check pull operation in update for
|
||||
EmbeddedDocumentListField which is inside a EmbeddedDocumentField
|
||||
"""
|
||||
|
||||
class Word(EmbeddedDocument):
|
||||
word = StringField()
|
||||
index = IntField()
|
||||
@@ -284,18 +347,27 @@ class TransformTest(unittest.TestCase):
|
||||
title = StringField()
|
||||
content = EmbeddedDocumentField(SubDoc)
|
||||
|
||||
word = Word(word='abc', index=1)
|
||||
word = Word(word="abc", index=1)
|
||||
update = transform.update(MainDoc, pull__content__text=word)
|
||||
self.assertEqual(update, {'$pull': {'content.text': SON([('word', u'abc'), ('index', 1)])}})
|
||||
self.assertEqual(
|
||||
update, {"$pull": {"content.text": SON([("word", u"abc"), ("index", 1)])}}
|
||||
)
|
||||
|
||||
update = transform.update(MainDoc, pull__content__heading='xyz')
|
||||
self.assertEqual(update, {'$pull': {'content.heading': 'xyz'}})
|
||||
update = transform.update(MainDoc, pull__content__heading="xyz")
|
||||
self.assertEqual(update, {"$pull": {"content.heading": "xyz"}})
|
||||
|
||||
update = transform.update(MainDoc, pull__content__text__word__in=['foo', 'bar'])
|
||||
self.assertEqual(update, {'$pull': {'content.text': {'word': {'$in': ['foo', 'bar']}}}})
|
||||
update = transform.update(MainDoc, pull__content__text__word__in=["foo", "bar"])
|
||||
self.assertEqual(
|
||||
update, {"$pull": {"content.text": {"word": {"$in": ["foo", "bar"]}}}}
|
||||
)
|
||||
|
||||
update = transform.update(MainDoc, pull__content__text__word__nin=['foo', 'bar'])
|
||||
self.assertEqual(update, {'$pull': {'content.text': {'word': {'$nin': ['foo', 'bar']}}}})
|
||||
update = transform.update(
|
||||
MainDoc, pull__content__text__word__nin=["foo", "bar"]
|
||||
)
|
||||
self.assertEqual(
|
||||
update, {"$pull": {"content.text": {"word": {"$nin": ["foo", "bar"]}}}}
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -12,14 +12,13 @@ __all__ = ("QTest",)
|
||||
|
||||
|
||||
class QTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
connect(db='mongoenginetest')
|
||||
connect(db="mongoenginetest")
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
age = IntField()
|
||||
meta = {'allow_inheritance': True}
|
||||
meta = {"allow_inheritance": True}
|
||||
|
||||
Person.drop_collection()
|
||||
self.Person = Person
|
||||
@@ -30,22 +29,22 @@ class QTest(unittest.TestCase):
|
||||
q1 = Q()
|
||||
q2 = Q(age__gte=18)
|
||||
q3 = Q()
|
||||
q4 = Q(name='test')
|
||||
q4 = Q(name="test")
|
||||
q5 = Q()
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
age = IntField()
|
||||
|
||||
query = {'$or': [{'age': {'$gte': 18}}, {'name': 'test'}]}
|
||||
query = {"$or": [{"age": {"$gte": 18}}, {"name": "test"}]}
|
||||
self.assertEqual((q1 | q2 | q3 | q4 | q5).to_query(Person), query)
|
||||
|
||||
query = {'age': {'$gte': 18}, 'name': 'test'}
|
||||
query = {"age": {"$gte": 18}, "name": "test"}
|
||||
self.assertEqual((q1 & q2 & q3 & q4 & q5).to_query(Person), query)
|
||||
|
||||
def test_q_with_dbref(self):
|
||||
"""Ensure Q objects handle DBRefs correctly"""
|
||||
connect(db='mongoenginetest')
|
||||
connect(db="mongoenginetest")
|
||||
|
||||
class User(Document):
|
||||
pass
|
||||
@@ -62,15 +61,18 @@ class QTest(unittest.TestCase):
|
||||
def test_and_combination(self):
|
||||
"""Ensure that Q-objects correctly AND together.
|
||||
"""
|
||||
|
||||
class TestDoc(Document):
|
||||
x = IntField()
|
||||
y = StringField()
|
||||
|
||||
query = (Q(x__lt=7) & Q(x__lt=3)).to_query(TestDoc)
|
||||
self.assertEqual(query, {'$and': [{'x': {'$lt': 7}}, {'x': {'$lt': 3}}]})
|
||||
self.assertEqual(query, {"$and": [{"x": {"$lt": 7}}, {"x": {"$lt": 3}}]})
|
||||
|
||||
query = (Q(y="a") & Q(x__lt=7) & Q(x__lt=3)).to_query(TestDoc)
|
||||
self.assertEqual(query, {'$and': [{'y': "a"}, {'x': {'$lt': 7}}, {'x': {'$lt': 3}}]})
|
||||
self.assertEqual(
|
||||
query, {"$and": [{"y": "a"}, {"x": {"$lt": 7}}, {"x": {"$lt": 3}}]}
|
||||
)
|
||||
|
||||
# Check normal cases work without an error
|
||||
query = Q(x__lt=7) & Q(x__gt=3)
|
||||
@@ -78,69 +80,74 @@ class QTest(unittest.TestCase):
|
||||
q1 = Q(x__lt=7)
|
||||
q2 = Q(x__gt=3)
|
||||
query = (q1 & q2).to_query(TestDoc)
|
||||
self.assertEqual(query, {'x': {'$lt': 7, '$gt': 3}})
|
||||
self.assertEqual(query, {"x": {"$lt": 7, "$gt": 3}})
|
||||
|
||||
# More complex nested example
|
||||
query = Q(x__lt=100) & Q(y__ne='NotMyString')
|
||||
query &= Q(y__in=['a', 'b', 'c']) & Q(x__gt=-100)
|
||||
query = Q(x__lt=100) & Q(y__ne="NotMyString")
|
||||
query &= Q(y__in=["a", "b", "c"]) & Q(x__gt=-100)
|
||||
mongo_query = {
|
||||
'x': {'$lt': 100, '$gt': -100},
|
||||
'y': {'$ne': 'NotMyString', '$in': ['a', 'b', 'c']},
|
||||
"x": {"$lt": 100, "$gt": -100},
|
||||
"y": {"$ne": "NotMyString", "$in": ["a", "b", "c"]},
|
||||
}
|
||||
self.assertEqual(query.to_query(TestDoc), mongo_query)
|
||||
|
||||
def test_or_combination(self):
|
||||
"""Ensure that Q-objects correctly OR together.
|
||||
"""
|
||||
|
||||
class TestDoc(Document):
|
||||
x = IntField()
|
||||
|
||||
q1 = Q(x__lt=3)
|
||||
q2 = Q(x__gt=7)
|
||||
query = (q1 | q2).to_query(TestDoc)
|
||||
self.assertEqual(query, {
|
||||
'$or': [
|
||||
{'x': {'$lt': 3}},
|
||||
{'x': {'$gt': 7}},
|
||||
]
|
||||
})
|
||||
self.assertEqual(query, {"$or": [{"x": {"$lt": 3}}, {"x": {"$gt": 7}}]})
|
||||
|
||||
def test_and_or_combination(self):
|
||||
"""Ensure that Q-objects handle ANDing ORed components.
|
||||
"""
|
||||
|
||||
class TestDoc(Document):
|
||||
x = IntField()
|
||||
y = BooleanField()
|
||||
|
||||
TestDoc.drop_collection()
|
||||
|
||||
query = (Q(x__gt=0) | Q(x__exists=False))
|
||||
query = Q(x__gt=0) | Q(x__exists=False)
|
||||
query &= Q(x__lt=100)
|
||||
self.assertEqual(query.to_query(TestDoc), {'$and': [
|
||||
{'$or': [{'x': {'$gt': 0}},
|
||||
{'x': {'$exists': False}}]},
|
||||
{'x': {'$lt': 100}}]
|
||||
})
|
||||
self.assertEqual(
|
||||
query.to_query(TestDoc),
|
||||
{
|
||||
"$and": [
|
||||
{"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]},
|
||||
{"x": {"$lt": 100}},
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
q1 = (Q(x__gt=0) | Q(x__exists=False))
|
||||
q2 = (Q(x__lt=100) | Q(y=True))
|
||||
q1 = Q(x__gt=0) | Q(x__exists=False)
|
||||
q2 = Q(x__lt=100) | Q(y=True)
|
||||
query = (q1 & q2).to_query(TestDoc)
|
||||
|
||||
TestDoc(x=101).save()
|
||||
TestDoc(x=10).save()
|
||||
TestDoc(y=True).save()
|
||||
|
||||
self.assertEqual(query, {
|
||||
'$and': [
|
||||
{'$or': [{'x': {'$gt': 0}}, {'x': {'$exists': False}}]},
|
||||
{'$or': [{'x': {'$lt': 100}}, {'y': True}]}
|
||||
]
|
||||
})
|
||||
self.assertEqual(
|
||||
query,
|
||||
{
|
||||
"$and": [
|
||||
{"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]},
|
||||
{"$or": [{"x": {"$lt": 100}}, {"y": True}]},
|
||||
]
|
||||
},
|
||||
)
|
||||
self.assertEqual(2, TestDoc.objects(q1 & q2).count())
|
||||
|
||||
def test_or_and_or_combination(self):
|
||||
"""Ensure that Q-objects handle ORing ANDed ORed components. :)
|
||||
"""
|
||||
|
||||
class TestDoc(Document):
|
||||
x = IntField()
|
||||
y = BooleanField()
|
||||
@@ -151,18 +158,29 @@ class QTest(unittest.TestCase):
|
||||
TestDoc(x=99, y=False).save()
|
||||
TestDoc(x=101, y=False).save()
|
||||
|
||||
q1 = (Q(x__gt=0) & (Q(y=True) | Q(y__exists=False)))
|
||||
q2 = (Q(x__lt=100) & (Q(y=False) | Q(y__exists=False)))
|
||||
q1 = Q(x__gt=0) & (Q(y=True) | Q(y__exists=False))
|
||||
q2 = Q(x__lt=100) & (Q(y=False) | Q(y__exists=False))
|
||||
query = (q1 | q2).to_query(TestDoc)
|
||||
|
||||
self.assertEqual(query, {
|
||||
'$or': [
|
||||
{'$and': [{'x': {'$gt': 0}},
|
||||
{'$or': [{'y': True}, {'y': {'$exists': False}}]}]},
|
||||
{'$and': [{'x': {'$lt': 100}},
|
||||
{'$or': [{'y': False}, {'y': {'$exists': False}}]}]}
|
||||
]
|
||||
})
|
||||
self.assertEqual(
|
||||
query,
|
||||
{
|
||||
"$or": [
|
||||
{
|
||||
"$and": [
|
||||
{"x": {"$gt": 0}},
|
||||
{"$or": [{"y": True}, {"y": {"$exists": False}}]},
|
||||
]
|
||||
},
|
||||
{
|
||||
"$and": [
|
||||
{"x": {"$lt": 100}},
|
||||
{"$or": [{"y": False}, {"y": {"$exists": False}}]},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
self.assertEqual(2, TestDoc.objects(q1 | q2).count())
|
||||
|
||||
def test_multiple_occurence_in_field(self):
|
||||
@@ -170,8 +188,8 @@ class QTest(unittest.TestCase):
|
||||
name = StringField(max_length=40)
|
||||
title = StringField(max_length=40)
|
||||
|
||||
q1 = Q(name__contains='te') | Q(title__contains='te')
|
||||
q2 = Q(name__contains='12') | Q(title__contains='12')
|
||||
q1 = Q(name__contains="te") | Q(title__contains="te")
|
||||
q2 = Q(name__contains="12") | Q(title__contains="12")
|
||||
|
||||
q3 = q1 & q2
|
||||
|
||||
@@ -180,7 +198,6 @@ class QTest(unittest.TestCase):
|
||||
self.assertEqual(query["$and"][1], q2.to_query(Test))
|
||||
|
||||
def test_q_clone(self):
|
||||
|
||||
class TestDoc(Document):
|
||||
x = IntField()
|
||||
|
||||
@@ -205,6 +222,7 @@ class QTest(unittest.TestCase):
|
||||
def test_q(self):
|
||||
"""Ensure that Q objects may be used to query for documents.
|
||||
"""
|
||||
|
||||
class BlogPost(Document):
|
||||
title = StringField()
|
||||
publish_date = DateTimeField()
|
||||
@@ -212,22 +230,26 @@ class QTest(unittest.TestCase):
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
post1 = BlogPost(title='Test 1', publish_date=datetime.datetime(2010, 1, 8), published=False)
|
||||
post1 = BlogPost(
|
||||
title="Test 1", publish_date=datetime.datetime(2010, 1, 8), published=False
|
||||
)
|
||||
post1.save()
|
||||
|
||||
post2 = BlogPost(title='Test 2', publish_date=datetime.datetime(2010, 1, 15), published=True)
|
||||
post2 = BlogPost(
|
||||
title="Test 2", publish_date=datetime.datetime(2010, 1, 15), published=True
|
||||
)
|
||||
post2.save()
|
||||
|
||||
post3 = BlogPost(title='Test 3', published=True)
|
||||
post3 = BlogPost(title="Test 3", published=True)
|
||||
post3.save()
|
||||
|
||||
post4 = BlogPost(title='Test 4', publish_date=datetime.datetime(2010, 1, 8))
|
||||
post4 = BlogPost(title="Test 4", publish_date=datetime.datetime(2010, 1, 8))
|
||||
post4.save()
|
||||
|
||||
post5 = BlogPost(title='Test 1', publish_date=datetime.datetime(2010, 1, 15))
|
||||
post5 = BlogPost(title="Test 1", publish_date=datetime.datetime(2010, 1, 15))
|
||||
post5.save()
|
||||
|
||||
post6 = BlogPost(title='Test 1', published=False)
|
||||
post6 = BlogPost(title="Test 1", published=False)
|
||||
post6.save()
|
||||
|
||||
# Check ObjectId lookup works
|
||||
@@ -235,13 +257,13 @@ class QTest(unittest.TestCase):
|
||||
self.assertEqual(obj, post1)
|
||||
|
||||
# Check Q object combination with one does not exist
|
||||
q = BlogPost.objects(Q(title='Test 5') | Q(published=True))
|
||||
q = BlogPost.objects(Q(title="Test 5") | Q(published=True))
|
||||
posts = [post.id for post in q]
|
||||
|
||||
published_posts = (post2, post3)
|
||||
self.assertTrue(all(obj.id in posts for obj in published_posts))
|
||||
|
||||
q = BlogPost.objects(Q(title='Test 1') | Q(published=True))
|
||||
q = BlogPost.objects(Q(title="Test 1") | Q(published=True))
|
||||
posts = [post.id for post in q]
|
||||
published_posts = (post1, post2, post3, post5, post6)
|
||||
self.assertTrue(all(obj.id in posts for obj in published_posts))
|
||||
@@ -259,85 +281,91 @@ class QTest(unittest.TestCase):
|
||||
BlogPost.drop_collection()
|
||||
|
||||
# Check the 'in' operator
|
||||
self.Person(name='user1', age=20).save()
|
||||
self.Person(name='user2', age=20).save()
|
||||
self.Person(name='user3', age=30).save()
|
||||
self.Person(name='user4', age=40).save()
|
||||
self.Person(name="user1", age=20).save()
|
||||
self.Person(name="user2", age=20).save()
|
||||
self.Person(name="user3", age=30).save()
|
||||
self.Person(name="user4", age=40).save()
|
||||
|
||||
self.assertEqual(self.Person.objects(Q(age__in=[20])).count(), 2)
|
||||
self.assertEqual(self.Person.objects(Q(age__in=[20, 30])).count(), 3)
|
||||
|
||||
# Test invalid query objs
|
||||
with self.assertRaises(InvalidQueryError):
|
||||
self.Person.objects('user1')
|
||||
self.Person.objects("user1")
|
||||
|
||||
# filter should fail, too
|
||||
with self.assertRaises(InvalidQueryError):
|
||||
self.Person.objects.filter('user1')
|
||||
self.Person.objects.filter("user1")
|
||||
|
||||
def test_q_regex(self):
|
||||
"""Ensure that Q objects can be queried using regexes.
|
||||
"""
|
||||
person = self.Person(name='Guido van Rossum')
|
||||
person = self.Person(name="Guido van Rossum")
|
||||
person.save()
|
||||
|
||||
obj = self.Person.objects(Q(name=re.compile('^Gui'))).first()
|
||||
obj = self.Person.objects(Q(name=re.compile("^Gui"))).first()
|
||||
self.assertEqual(obj, person)
|
||||
obj = self.Person.objects(Q(name=re.compile('^gui'))).first()
|
||||
obj = self.Person.objects(Q(name=re.compile("^gui"))).first()
|
||||
self.assertEqual(obj, None)
|
||||
|
||||
obj = self.Person.objects(Q(name=re.compile('^gui', re.I))).first()
|
||||
obj = self.Person.objects(Q(name=re.compile("^gui", re.I))).first()
|
||||
self.assertEqual(obj, person)
|
||||
|
||||
obj = self.Person.objects(Q(name__not=re.compile('^bob'))).first()
|
||||
obj = self.Person.objects(Q(name__not=re.compile("^bob"))).first()
|
||||
self.assertEqual(obj, person)
|
||||
|
||||
obj = self.Person.objects(Q(name__not=re.compile('^Gui'))).first()
|
||||
obj = self.Person.objects(Q(name__not=re.compile("^Gui"))).first()
|
||||
self.assertEqual(obj, None)
|
||||
|
||||
def test_q_repr(self):
|
||||
self.assertEqual(repr(Q()), 'Q(**{})')
|
||||
self.assertEqual(repr(Q(name='test')), "Q(**{'name': 'test'})")
|
||||
self.assertEqual(repr(Q()), "Q(**{})")
|
||||
self.assertEqual(repr(Q(name="test")), "Q(**{'name': 'test'})")
|
||||
|
||||
self.assertEqual(
|
||||
repr(Q(name='test') & Q(age__gte=18)),
|
||||
"(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))")
|
||||
repr(Q(name="test") & Q(age__gte=18)),
|
||||
"(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
repr(Q(name='test') | Q(age__gte=18)),
|
||||
"(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))")
|
||||
repr(Q(name="test") | Q(age__gte=18)),
|
||||
"(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))",
|
||||
)
|
||||
|
||||
def test_q_lists(self):
|
||||
"""Ensure that Q objects query ListFields correctly.
|
||||
"""
|
||||
|
||||
class BlogPost(Document):
|
||||
tags = ListField(StringField())
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
BlogPost(tags=['python', 'mongo']).save()
|
||||
BlogPost(tags=['python']).save()
|
||||
BlogPost(tags=["python", "mongo"]).save()
|
||||
BlogPost(tags=["python"]).save()
|
||||
|
||||
self.assertEqual(BlogPost.objects(Q(tags='mongo')).count(), 1)
|
||||
self.assertEqual(BlogPost.objects(Q(tags='python')).count(), 2)
|
||||
self.assertEqual(BlogPost.objects(Q(tags="mongo")).count(), 1)
|
||||
self.assertEqual(BlogPost.objects(Q(tags="python")).count(), 2)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
def test_q_merge_queries_edge_case(self):
|
||||
|
||||
class User(Document):
|
||||
email = EmailField(required=False)
|
||||
name = StringField()
|
||||
|
||||
User.drop_collection()
|
||||
pk = ObjectId()
|
||||
User(email='example@example.com', pk=pk).save()
|
||||
User(email="example@example.com", pk=pk).save()
|
||||
|
||||
self.assertEqual(1, User.objects.filter(Q(email='example@example.com') |
|
||||
Q(name='John Doe')).limit(2).filter(pk=pk).count())
|
||||
self.assertEqual(
|
||||
1,
|
||||
User.objects.filter(Q(email="example@example.com") | Q(name="John Doe"))
|
||||
.limit(2)
|
||||
.filter(pk=pk)
|
||||
.count(),
|
||||
)
|
||||
|
||||
def test_chained_q_or_filtering(self):
|
||||
|
||||
class Post(EmbeddedDocument):
|
||||
name = StringField(required=True)
|
||||
|
||||
@@ -350,9 +378,16 @@ class QTest(unittest.TestCase):
|
||||
Item(postables=[Post(name="a"), Post(name="c")]).save()
|
||||
Item(postables=[Post(name="a"), Post(name="b"), Post(name="c")]).save()
|
||||
|
||||
self.assertEqual(Item.objects(Q(postables__name="a") & Q(postables__name="b")).count(), 2)
|
||||
self.assertEqual(Item.objects.filter(postables__name="a").filter(postables__name="b").count(), 2)
|
||||
self.assertEqual(
|
||||
Item.objects(Q(postables__name="a") & Q(postables__name="b")).count(), 2
|
||||
)
|
||||
self.assertEqual(
|
||||
Item.objects.filter(postables__name="a")
|
||||
.filter(postables__name="b")
|
||||
.count(),
|
||||
2,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user