Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist/
minimongo.egg-info/
minimongo/app_config.py
pymongo-*/
venv
4 changes: 3 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ you can use ``easy_install -U minimongo``. Otherwise, you can download the
source from `GitHub <http://github.com/slacy/minimongo>`_ 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 <http://sphinx.pocoo.org>`_ (optional -- for documentation generation)


Expand Down
1 change: 1 addition & 0 deletions minimongo/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
42 changes: 26 additions & 16 deletions minimongo/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions minimongo/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 1 addition & 3 deletions minimongo/tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand All @@ -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",
)