diff --git a/.gitignore b/.gitignore index a2b31ea..4b93e5a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist/ minimongo.egg-info/ minimongo/app_config.py pymongo-*/ +venv diff --git a/README.rst b/README.rst index 75eed53..2c75658 100644 --- a/README.rst +++ b/README.rst @@ -28,10 +28,12 @@ you can use ``easy_install -U minimongo``. Otherwise, you can download the source from `GitHub `_ and run ``python setup.py install``. +Instead of installing as above, you should use `pip install -e .`. + Dependencies ============ -- pymongo_ 1.9+ +- pymongo_ 2.8+ - `sphinx `_ (optional -- for documentation generation) diff --git a/minimongo/collection.py b/minimongo/collection.py index 1ebcb07..1544469 100644 --- a/minimongo/collection.py +++ b/minimongo/collection.py @@ -8,6 +8,7 @@ class Cursor(PyMongoCursor): def __init__(self, *args, **kwargs): self._wrapper_class = kwargs.pop('wrap') + kwargs['projection'] = kwargs.pop('fields', None) super(Cursor, self).__init__(*args, **kwargs) def next(self): diff --git a/minimongo/model.py b/minimongo/model.py index 023ef34..79e8ec5 100644 --- a/minimongo/model.py +++ b/minimongo/model.py @@ -2,11 +2,13 @@ from __future__ import absolute_import import copy +import logging import re import six from bson import DBRef, ObjectId -from pymongo import MongoClient as Connection +from pymongo import MongoClient, MongoReplicaSetClient +from pymongo.read_preferences import ReadPreference from .collection import DummyCollection from .options import _Options @@ -19,7 +21,7 @@ class ModelBase(type): populated from the parrent's Meta if any. """ - # A very rudimentary connection pool. + # A very rudimentary connection pool, keyed by replicaSet name. _connections = {} def __new__(mcs, name, bases, attrs): @@ -53,23 +55,30 @@ def __new__(mcs, name, bases, attrs): 'Model %r improperly configured: %s %s %s' % ( name, options.host, options.port, options.database)) - # Checking connection pool for an existing connection. - hostport = options.host, options.port - if hostport in mcs._connections: - connection = mcs._connections[hostport] + # Checking connection / client pool for an existing connection / client. + pool_key = options.host,options.port + if options.replica_set_name: + logging.debug("Using replica_set_name=%s as database pool key." % options.replica_set_name) + pool_key = options.replica_set_name + + if pool_key in mcs._connections: + client = mcs._connections[pool_key] + logging.debug("Got database client from pool for pool_key=%s" % (pool_key,)) else: - # _connect=False option - # creates :class:`pymongo.connection.Connection` object without - # establishing connection. It's required if there is no running - # mongodb at this time but we want to create :class:`Model`. - # False option doesn't work with pymongo 2.4 using master/slave - # cluster - connection = Connection(*hostport) - mcs._connections[hostport] = connection + logging.debug("Creating new database client for pool_key=%s" % (pool_key,)) + if options.replica_set_name: + logging.debug("Setting up a replica set client...") + client = MongoReplicaSetClient(options.replica_set_uri, replicaSet=options.replica_set_name) + client.read_preference = ReadPreference.SECONDARY_PREFERRED + else: + logging.debug("Setting up a normal client...") + client = MongoClient(options.host, options.port) + + mcs._connections[pool_key] = client new_class._meta = options - new_class.connection = connection - new_class.database = connection[options.database] + new_class.connection = client + new_class.database = client[options.database] if options.username and options.password: new_class.database.authenticate(options.username, options.password) new_class.collection = options.collection_class( @@ -219,6 +228,7 @@ def mongo_update(self, values=None, **kwargs): def save(self, *args, **kwargs): """Save this object to it's mongo collection.""" + kwargs.pop('safe', None) self.collection.save(self, *args, **kwargs) return self diff --git a/minimongo/options.py b/minimongo/options.py index e9b15e5..c7c2849 100644 --- a/minimongo/options.py +++ b/minimongo/options.py @@ -56,6 +56,10 @@ class _Options(object): username = None password = None + # Replica set details. + replica_set_name = None + replica_set_uri = None + # Should indices be created at startup? auto_index = True diff --git a/minimongo/tests/test_model.py b/minimongo/tests/test_model.py index 2bda954..d5feee9 100644 --- a/minimongo/tests/test_model.py +++ b/minimongo/tests/test_model.py @@ -480,9 +480,7 @@ def test_collection_class(): def test_str(): assert str(TestModel()) == 'TestModel({})' - assert str(TestModel({'foo': 'bar'})) == 'TestModel({\'foo\': \'bar\'})' - - assert str(TestModel({'foo': 'bar'})) == 'TestModel({\'foo\': \'bar\'})' + assert str(TestModel({'foo': 'bar'})) == 'TestModel({u\'foo\': u\'bar\'})' def test_auto_collection_name(): diff --git a/setup.py b/setup.py index a0e4ad5..d9d1d6a 100644 --- a/setup.py +++ b/setup.py @@ -46,12 +46,12 @@ def run(self): requires = ["pymongo"] setup(name="minimongo", - version="0.2.9", + version="0.3.4", packages=find_packages(), cmdclass={"test": PyTest}, platforms=["any"], - install_requires = ["pymongo<=2.8", "six"], + install_requires = ["pymongo>=2.9"], zip_safe=False, include_package_data=True, @@ -61,5 +61,5 @@ def run(self): long_description=LONG_DESCRIPTION, classifiers=CLASSIFIERS, keywords=["mongo", "mongodb", "pymongo", "orm"], - url="https://github.com/slacy/minimongo", + url="https://github.com/HappierApp/minimongo", )