Update the test matrix to reflect what's supported in 2019 (#2066)

Previously, we were running the test suite for several combinations of MongoDB,
Python, and PyMongo:
- PyPy, MongoDB v2.6, PyMongo v3.x (which really means v3.6.1 at the moment)
- Python v2.7, MongoDB v2.6, PyMongo v3.x
- Python v3.5, MongoDB v2.6, PyMongo v3.x
- Python v3.6, MongoDB v2.6, PyMongo v3.x
- Python v2.7, MongoDB v3.0, PyMongo v3.5.0
- Python v3.6, MongoDB v3.0, PyMongo v3.5.0
- Python v3.5, MongoDB v3.2, PyMongo v3.x
- Python v3.6, MongoDB v3.2, PyMongo v3.x
- Python v3.6, MongoDB v3.4, PyMongo v3.x
- Python v3.6, MongoDB v3.6, PyMongo v3.x

There were a couple issues with this setup:
1. MongoDB v2.6 – v3.2 have reached their End of Life already (v2.6 almost 3
   years ago!). See the "MongoDB Server" section on
   https://www.mongodb.com/support-policy.
2. We were only testing two recent-ish PyMongo versions (v3.5.0 & v3.6.1).
   We were not testing the oldest actively supported MongoDB/PyMongo/Python
   setup.

This PR updates the test matrix so that these problems are solved. For the
sake of simplicity, it does not yet attempt to cover MongoDB v4.0:
- PyPy, MongoDB v3.4, PyMongo v3.x (aka v3.6.1 at the moment)
- Python v2.7, MongoDB v3.4, PyMongo v3.x
- Python v3.5, MongoDB v3.4, PyMongo v3.x
- Python v3.6, MongoDB v3.4, PyMongo v3.x
- Python v2.7, MongoDB v3.4, PyMongo v3.4
- Python v3.6, MongoDB v3.6, PyMongo v3.x
This commit is contained in:
Stefan Wójcik 2019-05-31 11:01:15 +02:00 committed by GitHub
parent da3773bfe8
commit 4334955e39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 105 additions and 161 deletions

View File

@ -2,11 +2,18 @@
# PyMongo combinations. However, that would result in an overly long build
# with a very large number of jobs, hence we only test a subset of all the
# combinations:
# * MongoDB v2.6 is currently the "main" version tested against Python v2.7,
# v3.5, v3.6, PyPy, and PyMongo v3.x.
# * MongoDB v3.0 & v3.2 are tested against Python v2.7, v3.5 & v3.6
# and Pymongo v3.5 & v3.x
# * MongoDB v3.4 is tested against v3.6 and Pymongo v3.x
# * MongoDB v3.4 & the latest PyMongo v3.x is currently the "main" setup,
# tested against Python v2.7, v3.5, v3.6, and PyPy.
# * Besides that, we test the lowest actively supported Python/MongoDB/PyMongo
# combination: MongoDB v3.4, PyMongo v3.4, Python v2.7.
# * MongoDB v3.6 is tested against Python v3.6, and PyMongo v3.6, v3.7, v3.8.
#
# We should periodically check MongoDB Server versions supported by MongoDB
# Inc., add newly released versions to the test matrix, and remove versions
# which have reached their End of Life. See:
# 1. https://www.mongodb.com/support-policy.
# 2. https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#python-driver-compatibility
#
# Reminder: Update README.rst if you change MongoDB versions we test.
language: python
@ -18,7 +25,7 @@ python:
- pypy
env:
- MONGODB=2.6 PYMONGO=3.x
- MONGODB=3.4 PYMONGO=3.x
matrix:
# Finish the build as soon as one job fails
@ -26,15 +33,7 @@ matrix:
include:
- python: 2.7
env: MONGODB=3.0 PYMONGO=3.5
- python: 3.5
env: MONGODB=3.2 PYMONGO=3.x
- python: 3.6
env: MONGODB=3.0 PYMONGO=3.5
- python: 3.6
env: MONGODB=3.2 PYMONGO=3.x
- python: 3.6
env: MONGODB=3.4 PYMONGO=3.x
env: MONGODB=3.4 PYMONGO=3.4.x
- python: 3.6
env: MONGODB=3.6 PYMONGO=3.x
@ -86,15 +85,15 @@ deploy:
password:
secure: QMyatmWBnC6ZN3XLW2+fTBDU4LQcp1m/LjR2/0uamyeUzWKdlOoh/Wx5elOgLwt/8N9ppdPeG83ose1jOz69l5G0MUMjv8n/RIcMFSpCT59tGYqn3kh55b0cIZXFT9ar+5cxlif6a5rS72IHm5li7QQyxexJIII6Uxp0kpvUmek=
# create a source distribution and a pure python wheel for faster installs
# Create a source distribution and a pure python wheel for faster installs.
distributions: "sdist bdist_wheel"
# only deploy on tagged commits (aka GitHub releases) and only for the
# parent repo's builds running Python 2.7 along with PyMongo v3.x (we run
# Travis against many different Python and PyMongo versions and we don't
# want the deploy to occur multiple times).
# Only deploy on tagged commits (aka GitHub releases) and only for the parent
# repo's builds running Python v2.7 along with PyMongo v3.x and MongoDB v3.4.
# We run Travis against many different Python, PyMongo, and MongoDB versions
# and we don't want the deploy to occur multiple times).
on:
tags: true
repo: MongoEngine/mongoengine
condition: "$PYMONGO = 3.x"
condition: ($PYMONGO = 3.x) AND ($MONGODB = 3.4)
python: 2.7

View File

@ -26,10 +26,10 @@ an `API reference <https://mongoengine-odm.readthedocs.io/apireference.html>`_.
Supported MongoDB Versions
==========================
MongoEngine is currently tested against MongoDB v2.6, v3.0, v3.2, v3.4 and v3.6. Future
versions should be supported as well, but aren't actively tested at the moment.
Make sure to open an issue or submit a pull request if you experience any
problems with MongoDB v3.6+.
MongoEngine is currently tested against MongoDB v3.4 and v3.6. Future versions
should be supported as well, but aren't actively tested at the moment. Make
sure to open an issue or submit a pull request if you experience any problems
with MongoDB version > 3.6.
Installation
============

View File

@ -117,10 +117,22 @@ def _get_connection_settings(
ReadPreference.PRIMARY,
ReadPreference.PRIMARY_PREFERRED,
ReadPreference.SECONDARY,
ReadPreference.SECONDARY_PREFERRED)
read_pf_mode = uri_options['readpreference'].lower()
ReadPreference.SECONDARY_PREFERRED,
)
# Starting with PyMongo v3.5, the "readpreference" option is
# returned as a string (e.g. "secondaryPreferred") and not an
# int (e.g. 3).
# TODO simplify the code below once we drop support for
# PyMongo v3.4.
read_pf_mode = uri_options['readpreference']
if isinstance(read_pf_mode, six.string_types):
read_pf_mode = read_pf_mode.lower()
for preference in read_preferences:
if preference.name.lower() == read_pf_mode:
if (
preference.name.lower() == read_pf_mode or
preference.mode == read_pf_mode
):
conn_settings['read_preference'] = preference
break
else:

View File

@ -7,10 +7,6 @@ from mongoengine.connection import get_connection
# Constant that can be used to compare the version retrieved with
# get_mongodb_version()
MONGODB_36 = (3, 6)
MONGODB_34 = (3, 4)
MONGODB_32 = (3, 2)
MONGODB_3 = (3, 0)
MONGODB_26 = (2, 6)
def get_mongodb_version():

View File

@ -1,5 +1,5 @@
nose
pymongo>=3.5
pymongo>=3.4
six==1.10.0
flake8
flake8-import-order

View File

@ -80,7 +80,7 @@ setup(
long_description=LONG_DESCRIPTION,
platforms=['any'],
classifiers=CLASSIFIERS,
install_requires=['pymongo>=3.5', 'six'],
install_requires=['pymongo>=3.4', 'six'],
test_suite='nose.collector',
**extra_opts
)

View File

@ -6,7 +6,6 @@ from mongoengine.pymongo_support import list_collection_names
from mongoengine.queryset import NULLIFY, PULL
from mongoengine.connection import get_db
from tests.utils import requires_mongodb_gte_26
__all__ = ("ClassMethodsTest", )
@ -187,7 +186,6 @@ class ClassMethodsTest(unittest.TestCase):
self.assertEqual(BlogPostWithTags.compare_indexes(), {'missing': [], 'extra': []})
self.assertEqual(BlogPostWithCustomField.compare_indexes(), {'missing': [], 'extra': []})
@requires_mongodb_gte_26
def test_compare_indexes_for_text_indexes(self):
""" Ensure that compare_indexes behaves correctly for text indexes """

View File

@ -9,8 +9,7 @@ from six import iteritems
from mongoengine import *
from mongoengine.connection import get_db
from mongoengine.mongodb_support import get_mongodb_version, MONGODB_32, MONGODB_3
from tests.utils import requires_mongodb_gte_26, requires_mongodb_lte_32, requires_mongodb_gte_34
from mongoengine.mongodb_support import get_mongodb_version
__all__ = ("IndexesTest", )
@ -478,8 +477,6 @@ class IndexesTest(unittest.TestCase):
def test_covered_index(self):
"""Ensure that covered indexes can be used
"""
IS_MONGODB_3 = get_mongodb_version() >= MONGODB_3
class Test(Document):
a = IntField()
b = IntField()
@ -497,33 +494,38 @@ class IndexesTest(unittest.TestCase):
# Need to be explicit about covered indexes as mongoDB doesn't know if
# the documents returned might have more keys in that here.
query_plan = Test.objects(id=obj.id).exclude('a').explain()
if not IS_MONGODB_3:
self.assertFalse(query_plan['indexOnly'])
else:
self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IDHACK')
self.assertEqual(
query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'),
'IDHACK'
)
query_plan = Test.objects(id=obj.id).only('id').explain()
if not IS_MONGODB_3:
self.assertTrue(query_plan['indexOnly'])
else:
self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IDHACK')
self.assertEqual(
query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'),
'IDHACK'
)
query_plan = Test.objects(a=1).only('a').exclude('id').explain()
if not IS_MONGODB_3:
self.assertTrue(query_plan['indexOnly'])
else:
self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IXSCAN')
self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('stage'), 'PROJECTION')
self.assertEqual(
query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'),
'IXSCAN'
)
self.assertEqual(
query_plan.get('queryPlanner').get('winningPlan').get('stage'),
'PROJECTION'
)
query_plan = Test.objects(a=1).explain()
if not IS_MONGODB_3:
self.assertFalse(query_plan['indexOnly'])
else:
self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IXSCAN')
self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('stage'), 'FETCH')
self.assertEqual(
query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'),
'IXSCAN'
)
self.assertEqual(
query_plan.get('queryPlanner').get('winningPlan').get('stage'),
'FETCH'
)
def test_index_on_id(self):
class BlogPost(Document):
meta = {
'indexes': [
@ -565,13 +567,10 @@ class IndexesTest(unittest.TestCase):
self.assertEqual(BlogPost.objects.count(), 10)
self.assertEqual(BlogPost.objects.hint().count(), 10)
if MONGO_VER >= MONGODB_32:
# Mongo32 throws an error if an index exists (i.e `tags` in our case)
# and you use hint on an index name that does not exist
with self.assertRaises(OperationFailure):
BlogPost.objects.hint([('ZZ', 1)]).count()
else:
self.assertEqual(BlogPost.objects.hint([('ZZ', 1)]).count(), 10)
# MongoDB v3.2+ throws an error if an index exists (i.e `tags` in our
# case) and you use hint on an index name that does not exist.
with self.assertRaises(OperationFailure):
BlogPost.objects.hint([('ZZ', 1)]).count()
self.assertEqual(BlogPost.objects.hint(TAGS_INDEX_NAME).count(), 10)
@ -598,9 +597,8 @@ class IndexesTest(unittest.TestCase):
# Ensure backwards compatibility for errors
self.assertRaises(OperationError, post2.save)
@requires_mongodb_gte_34
def test_primary_key_unique_not_working_under_mongo_34(self):
"""Relates to #1445"""
def test_primary_key_unique_not_working(self):
"""Relates to #1445"""
class Blog(Document):
id = StringField(primary_key=True, unique=True)
@ -608,21 +606,17 @@ class IndexesTest(unittest.TestCase):
with self.assertRaises(OperationFailure) as ctx_err:
Blog(id='garbage').save()
try:
self.assertIn("The field 'unique' is not valid for an _id index specification", str(ctx_err.exception))
except AssertionError:
# error is slightly different on python 3.6
self.assertIn("The field 'background' is not valid for an _id index specification", str(ctx_err.exception))
@requires_mongodb_lte_32
def test_primary_key_unique_working_under_mongo_32(self):
"""Relates to #1445"""
class Blog(Document):
id = StringField(primary_key=True, unique=True)
Blog.drop_collection()
Blog(id='garbage').save()
# One of the errors below should happen. Which one depends on the
# PyMongo version and dict order.
err_msg = str(ctx_err.exception)
self.assertTrue(
any([
"The field 'unique' is not valid for an _id index specification" in err_msg,
"The field 'background' is not valid for an _id index specification" in err_msg,
"The field 'sparse' is not valid for an _id index specification" in err_msg,
])
)
def test_unique_with(self):
"""Ensure that unique_with constraints are applied to fields.
@ -984,7 +978,6 @@ class IndexesTest(unittest.TestCase):
info['provider_ids.foo_1_provider_ids.bar_1']['key'])
self.assertTrue(info['provider_ids.foo_1_provider_ids.bar_1']['sparse'])
@requires_mongodb_gte_26
def test_text_indexes(self):
class Book(Document):
title = DictField()

View File

@ -28,8 +28,6 @@ from mongoengine.queryset import NULLIFY, Q
from mongoengine.context_managers import switch_db, query_counter
from mongoengine import signals
from tests.utils import requires_mongodb_gte_26
TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__),
'../fields/mongoengine.png')
@ -850,7 +848,6 @@ class InstanceTest(MongoDBTestCase):
self.assertDbEqual([dict(other_doc.to_mongo()), dict(doc.to_mongo())])
@requires_mongodb_gte_26
def test_modify_with_positional_push(self):
class Content(EmbeddedDocument):
keywords = ListField(StringField())
@ -3368,7 +3365,6 @@ class InstanceTest(MongoDBTestCase):
person.update(set__height=2.0)
@requires_mongodb_gte_26
def test_push_with_position(self):
"""Ensure that push with position works properly for an instance."""
class BlogPost(Document):

View File

@ -3,7 +3,7 @@ import unittest
from mongoengine import *
from tests.utils import MongoDBTestCase, requires_mongodb_gte_3
from tests.utils import MongoDBTestCase
__all__ = ("GeoQueriesTest",)
@ -70,9 +70,6 @@ class GeoQueriesTest(MongoDBTestCase):
self.assertEqual(events.count(), 1)
self.assertEqual(events[0], event2)
# $minDistance was added in MongoDB v2.6, but continued being buggy
# until v3.0; skip for older versions
@requires_mongodb_gte_3
def test_near_and_min_distance(self):
"""Ensure the "min_distance" operator works alongside the "near"
operator.
@ -243,9 +240,6 @@ class GeoQueriesTest(MongoDBTestCase):
events = self.Event.objects(location__geo_within_polygon=polygon2)
self.assertEqual(events.count(), 0)
# $minDistance was added in MongoDB v2.6, but continued being buggy
# until v3.0; skip for older versions
@requires_mongodb_gte_3
def test_2dsphere_near_and_min_max_distance(self):
"""Ensure "min_distace" and "max_distance" operators work well
together with the "near" operator in a 2dsphere index.
@ -328,8 +322,6 @@ class GeoQueriesTest(MongoDBTestCase):
"""Make sure PointField works properly in an embedded document."""
self._test_embedded(point_field_class=PointField)
# Needs MongoDB > 2.6.4 https://jira.mongodb.org/browse/SERVER-14039
@requires_mongodb_gte_3
def test_spherical_geospatial_operators(self):
"""Ensure that spherical geospatial queries are working."""
class Point(Document):

View File

@ -2,8 +2,6 @@ import unittest
from mongoengine import connect, Document, IntField, StringField, ListField
from tests.utils import requires_mongodb_gte_26
__all__ = ("FindAndModifyTest",)
@ -96,7 +94,6 @@ class FindAndModifyTest(unittest.TestCase):
self.assertEqual(old_doc.to_mongo(), {"_id": 1})
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
@requires_mongodb_gte_26
def test_modify_with_push(self):
class BlogPost(Document):
tags = ListField(StringField())

View File

@ -17,10 +17,9 @@ from mongoengine import *
from mongoengine.connection import get_connection, get_db
from mongoengine.context_managers import query_counter, switch_db
from mongoengine.errors import InvalidQueryError
from mongoengine.mongodb_support import get_mongodb_version, MONGODB_32, MONGODB_36
from mongoengine.mongodb_support import get_mongodb_version, MONGODB_36
from mongoengine.queryset import (DoesNotExist, MultipleObjectsReturned,
QuerySet, QuerySetManager, queryset_manager)
from tests.utils import requires_mongodb_gte_26
class db_ops_tracker(query_counter):
@ -32,7 +31,7 @@ class db_ops_tracker(query_counter):
def get_key_compat(mongo_ver):
ORDER_BY_KEY = 'sort' if mongo_ver >= MONGODB_32 else '$orderby'
ORDER_BY_KEY = 'sort'
CMD_QUERY_KEY = 'command' if mongo_ver >= MONGODB_36 else 'query'
return ORDER_BY_KEY, CMD_QUERY_KEY
@ -598,7 +597,6 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(post.comments[0].by, 'joe')
self.assertEqual(post.comments[0].votes.score, 4)
@requires_mongodb_gte_26
def test_update_min_max(self):
class Scores(Document):
high_score = IntField()
@ -616,7 +614,6 @@ class QuerySetTest(unittest.TestCase):
Scores.objects(id=scores.id).update(max__high_score=500)
self.assertEqual(Scores.objects.get(id=scores.id).high_score, 1000)
@requires_mongodb_gte_26
def test_update_multiple(self):
class Product(Document):
item = StringField()
@ -868,11 +865,7 @@ class QuerySetTest(unittest.TestCase):
with query_counter() as q:
self.assertEqual(q, 0)
Blog.objects.insert(blogs, load_bulk=False)
if MONGO_VER >= MONGODB_32:
self.assertEqual(q, 1) # 1 entry containing the list of inserts
else:
self.assertEqual(q, len(blogs)) # 1 entry per doc inserted
self.assertEqual(q, 1) # 1 entry containing the list of inserts
self.assertEqual(Blog.objects.count(), len(blogs))
@ -885,11 +878,7 @@ class QuerySetTest(unittest.TestCase):
with query_counter() as q:
self.assertEqual(q, 0)
Blog.objects.insert(blogs)
if MONGO_VER >= MONGODB_32:
self.assertEqual(q, 2) # 1 for insert 1 for fetch
else:
self.assertEqual(q, len(blogs)+1) # + 1 to fetch all docs
self.assertEqual(q, 2) # 1 for insert 1 for fetch
Blog.drop_collection()
@ -2030,7 +2019,6 @@ class QuerySetTest(unittest.TestCase):
pymongo_doc = BlogPost.objects.as_pymongo().first()
self.assertNotIn('title', pymongo_doc)
@requires_mongodb_gte_26
def test_update_push_with_position(self):
"""Ensure that the 'push' update with position works properly.
"""
@ -2555,8 +2543,8 @@ class QuerySetTest(unittest.TestCase):
"""Make sure adding a comment to the query gets added to the query"""
MONGO_VER = self.mongodb_version
_, CMD_QUERY_KEY = get_key_compat(MONGO_VER)
QUERY_KEY = 'filter' if MONGO_VER >= MONGODB_32 else '$query'
COMMENT_KEY = 'comment' if MONGO_VER >= MONGODB_32 else '$comment'
QUERY_KEY = 'filter'
COMMENT_KEY = 'comment'
class User(Document):
age = IntField()
@ -3370,7 +3358,6 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(Foo.objects.distinct("bar"), [bar])
@requires_mongodb_gte_26
def test_text_indexes(self):
class News(Document):
title = StringField()
@ -3454,7 +3441,6 @@ class QuerySetTest(unittest.TestCase):
'brasil').order_by('$text_score').first()
self.assertEqual(item.get_text_score(), max_text_score)
@requires_mongodb_gte_26
def test_distinct_handles_references_to_alias(self):
register_connection('testdb', 'mongoenginetest2')
@ -4586,7 +4572,6 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(bars._cursor._Cursor__read_preference,
ReadPreference.SECONDARY_PREFERRED)
@requires_mongodb_gte_26
def test_read_preference_aggregation_framework(self):
class Bar(Document):
txt = StringField()
@ -5354,7 +5339,6 @@ class QuerySetTest(unittest.TestCase):
self.assertTrue(Person.objects._has_data(),
'Cursor has data and returned False')
@requires_mongodb_gte_26
def test_queryset_aggregation_framework(self):
class Person(Document):
name = StringField()
@ -5396,7 +5380,6 @@ class QuerySetTest(unittest.TestCase):
{'_id': None, 'avg': 29, 'total': 2}
])
@requires_mongodb_gte_26
def test_queryset_aggregation_with_skip(self):
class Person(Document):
name = StringField()
@ -5418,7 +5401,6 @@ class QuerySetTest(unittest.TestCase):
{'_id': p3.pk, 'name': "SANDRA MARA"}
])
@requires_mongodb_gte_26
def test_queryset_aggregation_with_limit(self):
class Person(Document):
name = StringField()
@ -5439,7 +5421,6 @@ class QuerySetTest(unittest.TestCase):
{'_id': p1.pk, 'name': "ISABELLA LUANNA"}
])
@requires_mongodb_gte_26
def test_queryset_aggregation_with_sort(self):
class Person(Document):
name = StringField()
@ -5462,7 +5443,6 @@ class QuerySetTest(unittest.TestCase):
{'_id': p2.pk, 'name': "WILSON JUNIOR"}
])
@requires_mongodb_gte_26
def test_queryset_aggregation_with_skip_with_limit(self):
class Person(Document):
name = StringField()
@ -5492,7 +5472,6 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(data, list(data2))
@requires_mongodb_gte_26
def test_queryset_aggregation_with_sort_with_limit(self):
class Person(Document):
name = StringField()
@ -5534,7 +5513,6 @@ class QuerySetTest(unittest.TestCase):
{'_id': p3.pk, 'name': "SANDRA MARA"},
])
@requires_mongodb_gte_26
def test_queryset_aggregation_with_sort_with_skip(self):
class Person(Document):
name = StringField()
@ -5555,7 +5533,6 @@ class QuerySetTest(unittest.TestCase):
{'_id': p2.pk, 'name': "WILSON JUNIOR"}
])
@requires_mongodb_gte_26
def test_queryset_aggregation_with_sort_with_skip_with_limit(self):
class Person(Document):
name = StringField()

View File

@ -5,7 +5,7 @@ from nose.plugins.skip import SkipTest
from mongoengine import connect
from mongoengine.connection import get_db, disconnect_all
from mongoengine.mongodb_support import get_mongodb_version, MONGODB_26, MONGODB_3, MONGODB_32, MONGODB_34
from mongoengine.mongodb_support import get_mongodb_version
MONGO_TEST_DB = 'mongoenginetest' # standard name for the test database
@ -35,8 +35,20 @@ def get_as_pymongo(doc):
def _decorated_with_ver_requirement(func, mongo_version_req, oper):
"""Return a given function decorated with the version requirement
for a particular MongoDB version tuple.
"""Return a MongoDB version requirement decorator.
The resulting decorator will raise a SkipTest exception if the current
MongoDB version doesn't match the provided version/operator.
For example, if you define a decorator like so:
def requires_mongodb_gte_36(func):
return _decorated_with_ver_requirement(
func, (3.6), oper=operator.ge
)
Then tests decorated with @requires_mongodb_gte_36 will be skipped if
ran against MongoDB < v3.6.
:param mongo_version_req: The mongodb version requirement (tuple(int, int))
:param oper: The operator to apply (e.g: operator.ge)
@ -51,31 +63,3 @@ def _decorated_with_ver_requirement(func, mongo_version_req, oper):
_inner.__name__ = func.__name__
_inner.__doc__ = func.__doc__
return _inner
def requires_mongodb_gte_34(func):
"""Raise a SkipTest exception if we're working with MongoDB version
lower than v3.4
"""
return _decorated_with_ver_requirement(func, MONGODB_34, oper=operator.ge)
def requires_mongodb_lte_32(func):
"""Raise a SkipTest exception if we're working with MongoDB version
greater than v3.2.
"""
return _decorated_with_ver_requirement(func, MONGODB_32, oper=operator.le)
def requires_mongodb_gte_26(func):
"""Raise a SkipTest exception if we're working with MongoDB version
lower than v2.6.
"""
return _decorated_with_ver_requirement(func, MONGODB_26, oper=operator.ge)
def requires_mongodb_gte_3(func):
"""Raise a SkipTest exception if we're working with MongoDB version
lower than v3.0.
"""
return _decorated_with_ver_requirement(func, MONGODB_3, oper=operator.ge)

View File

@ -6,7 +6,7 @@ commands =
python setup.py nosetests {posargs}
deps =
nose
mg35: PyMongo==3.5
mg34x: PyMongo>=3.4,<3.5
mg3x: PyMongo>=3.0,<3.7
setenv =
PYTHON_EGG_CACHE = {envdir}/python-eggs