mongo-python-driver/mongo.py

135 lines
4.6 KiB
Python

"""Wrapper class for a Mongo database connection.
Adds some nice functionality."""
import socket
import types
import traceback
import struct
from database import Database
from connection import Connection
from son import SON
from objectid import ObjectId
from dbref import DBRef
from cursor_manager import BatchCursorManager
ASCENDING = 1
DESCENDING = -1
class Mongo(Database):
"""A connection to a Mongo database.
"""
def __init__(self, name, host="localhost", port=27017, settings={}):
"""Open a new connection to the database at host:port.
Raises TypeError if name or host is not an instance of string or port is
not an instance of int. Raises ConnectionFailure if the connection
cannot be made.
Settings are passed in as a dictionary. Possible settings, along with
their default values (in parens), are listed below:
- "auto_dereference" (False): automatically dereference any `DBRef`s
contained within SON objects being returned from queries
- "auto_reference" (False): automatically create `DBRef`s out of any
sub-objects that have already been saved in the database
Arguments:
- `name`: the name of the database to connect to
- `host` (optional): the hostname or IPv4 address of the database to
connect to
- `port` (optional): the port number on which to connect
- `settings` (optional): a dictionary of settings
"""
if not isinstance(settings, types.DictType):
raise TypeError("settings must be an instance of dict")
self.__auto_dereference = settings.get("auto_dereference", False)
self.__auto_reference = settings.get("auto_reference", False)
connection = Connection(host, port)
connection.set_cursor_manager(BatchCursorManager)
Database.__init__(self, connection, name)
def __repr__(self):
return "Mongo(%r, %r, %r)" % (self.name(), self.connection().host(), self.connection().port())
def dereference(self, dbref):
"""Dereference a DBRef, getting the SON object it points to.
Raises TypeError if dbref is not an instance of DBRef. Returns a SON
object or None if the reference does not point to a valid object.
Arguments:
- `dbref`: the reference
"""
if not isinstance(dbref, DBRef):
raise TypeError("cannot dereference a %s" % type(dbref))
return self[dbref.collection()].find_one(dbref.id())
def _fix_outgoing(self, son):
"""Fixes an object coming out of the database.
Used to do things like auto dereferencing, if the option is enabled.
Arguments:
- `son`: a SON object coming out of the database
"""
if not self.__auto_dereference:
return son
def fix_value(value):
if isinstance(value, DBRef):
deref = self.dereference(value)
if deref is None:
return value
return self._fix_outgoing(deref)
elif isinstance(value, (SON, types.DictType)):
return self._fix_outgoing(value)
elif isinstance(value, types.ListType):
return [fix_value(v) for v in value]
return value
for (key, value) in son.items():
son[key] = fix_value(value)
return son
def _fix_incoming(self, to_save, collection, add_meta):
"""Fixes an object going in to the database.
Used to do things like auto referencing, if the option is enabled.
Will also add _id and _ns if they are missing and desired (as specified
by add_meta).
Arguments:
- `to_save`: a SON object going into the database
- `collection`: collection into which this object is being saved
- `add_meta`: should _id and other meta-fields be added to the object
"""
if "_id" in to_save:
assert isinstance(to_save["_id"], ObjectId), "'_id' must be an ObjectId"
elif add_meta:
to_save["_id"] = ObjectId()
if add_meta:
to_save["_ns"] = collection._name()
if not self.__auto_reference:
return to_save
# make a copy, so only what is being saved gets auto-ref'ed
to_save = SON(to_save)
def fix_value(value):
if isinstance(value, (SON, types.DictType)):
if "_id" in value and not value["_id"].is_new() and "_ns" in value:
return DBRef(value["_ns"], value["_id"])
return value
for (key, value) in to_save.items():
to_save[key] = fix_value(value)
return to_save