|
| 1 | +""" |
| 2 | +Replica Set integration with for MongoKit |
| 3 | +Liyan Chang, liyan@filepicker.io |
| 4 | +(same license as Mongokit) |
| 5 | +""" |
| 6 | + |
| 7 | +from pymongo.replica_set_connection import ReplicaSetConnection as PymongoReplicaSetConnection |
| 8 | +from mongokit.database import Database |
| 9 | +from mongokit.connection import CallableMixin, _iterables |
| 10 | + |
| 11 | +class ReplicaSetConnection(PymongoReplicaSetConnection): |
| 12 | + """ Replica Set support for MongoKit """ |
| 13 | + |
| 14 | + def __init__(self, *args, **kwargs): |
| 15 | + """ The ReplicaSetConnection is a wrapper around the |
| 16 | + pymongo.replica_set_connection implementation. |
| 17 | + """ |
| 18 | + |
| 19 | + self._databases = {} |
| 20 | + self._registered_documents = {} |
| 21 | + |
| 22 | + super(ReplicaSetConnection, self).__init__(*args, **kwargs) |
| 23 | + |
| 24 | + """ |
| 25 | + All following code is duplicate code copied from connection.py |
| 26 | + Any edit to this code should probably be propagated over to |
| 27 | + connection.py as well as master_slave_connection.py |
| 28 | + """ |
| 29 | + |
| 30 | + def register(self, obj_list): |
| 31 | + decorator = None |
| 32 | + if not isinstance(obj_list, _iterables): |
| 33 | + # we assume that the user used this as a decorator |
| 34 | + # using @register syntax or using conn.register(SomeDoc) |
| 35 | + # we stock the class object in order to return it later |
| 36 | + decorator = obj_list |
| 37 | + obj_list = [obj_list] |
| 38 | + # cleanup |
| 39 | + for dbname, db in self._databases.items(): |
| 40 | + for colname, col in db._collections.items(): |
| 41 | + for docname, doc in col._documents.items(): |
| 42 | + del col._documents[docname] |
| 43 | + for obj_name in [obj.__name__ for obj in obj_list]: |
| 44 | + if obj_name in col._registered_documents: |
| 45 | + del col._registered_documents[obj_name] |
| 46 | + # register |
| 47 | + for obj in obj_list: |
| 48 | + CallableDocument = type( |
| 49 | + "Callable%s" % obj.__name__, |
| 50 | + (obj, CallableMixin), |
| 51 | + {"_obj_class":obj, "__repr__":object.__repr__} |
| 52 | + ) |
| 53 | + self._registered_documents[obj.__name__] = CallableDocument |
| 54 | + # if the class object is stored, it means the user used a decorator and |
| 55 | + # we must return the class object |
| 56 | + if decorator is not None: |
| 57 | + return decorator |
| 58 | + |
| 59 | + def __getattr__(self, key): |
| 60 | + if key in self._registered_documents: |
| 61 | + document = self._registered_documents[key] |
| 62 | + try: |
| 63 | + return getattr(self[document.__database__][document.__collection__], key) |
| 64 | + except AttributeError: |
| 65 | + raise AttributeError("%s: __collection__ attribute not found. " |
| 66 | + "You cannot specify the `__database__` attribute without " |
| 67 | + "the `__collection__` attribute" % key) |
| 68 | + else: |
| 69 | + if key not in self._databases: |
| 70 | + self._databases[key] = Database(self, key) |
| 71 | + return self._databases[key] |
| 72 | + |
0 commit comments