snakelet.storage.manager   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 167
rs 9.84
c 0
b 0
f 0
wmc 32

10 Methods

Rating   Name   Duplication   Size   Complexity  
A Manager.identify() 0 16 5
C Manager.hydrate() 0 25 9
A Manager.refresh() 0 10 2
A Manager.collection() 0 13 3
A Manager.save() 0 10 2
A Manager.objectify() 0 19 3
A Manager.shutdown() 0 6 1
A Manager.remove() 0 7 2
A Manager.__init__() 0 22 1
A Manager.register() 0 17 4
1
import inspect
2
3
from bson.dbref import DBRef
4
from pymongo import MongoClient
5
6
from .collection import Collection
7
from .document import Document
8
from ..utilities.conversion import Conversion
9
10
11
class Manager(object):
12
13
    def __init__(self, database, host=None, port=None, username=None, password=None, case=None):
14
        """
15
        :param database:
16
        :param host:
17
        :param port:
18
        :param username:
19
        :param password:
20
        :param case:
21
        """
22
        # Configuration
23
        self.collection_name = Conversion(case)
24
        self.document_name = Conversion('camel')
25
26
        # Driver
27
        self.client = MongoClient(host=host, port=port)
28
        self.client[database].authenticate(name=username, password=password)
29
        self.db = self.client[database]
30
31
        # Storage
32
        self.collections = {}
33
        self.documents = {}
34
        self.ref_types = (dict, list, DBRef)
35
36
    @staticmethod
37
    def identify(document):
38
        """
39
        Args:
40
            document:
41
42
        Returns:
43
            str: Name of document
44
        """
45
        isclass = inspect.isclass(document)
46
        if isclass and issubclass(document, Document):
47
            return document.__name__
48
        elif not isclass and isinstance(document, Document):
49
            return type(document).__name__
50
        else:
51
            raise TypeError('Value is not an instance or subclass of Document.')
52
53
    def collection(self, target):
54
        """
55
        Args:
56
            target:
57
58
        Returns:
59
            Collection:
60
        """
61
        if not isinstance(target, str):
62
            target = self.identify(target)
63
        if target not in self.collections:
64
            raise LookupError('Collection ' + target + ' does not exist.')
65
        return self.collections[target]
66
67
    def register(self, *args):
68
        """
69
        Args:
70
            *args: One or more documents
71
72
        Returns:
73
74
        """
75
        for document in args:
76
            if not issubclass(document, Document):
77
                continue
78
            identifier = self.identify(document)
79
            if identifier in self.documents:
80
                raise LookupError('Document ' + identifier + ' is already registered.')
81
            self.documents[identifier] = document
82
            self.collections[identifier] = Collection(self, document)
83
            self.__setattr__(identifier, Collection(self, document))
84
85
    def objectify(self, collection, document):
86
        """
87
        Args:
88
            collection:
89
            document:
90
91
        Returns:
92
            Document:
93
        """
94
        # TODO: This should probably access the correct collection instead
95
        name = self.document_name.encode(collection)
96
        if name in self.documents:
97
            prototype = self.documents[name]()
98
            if document:
99
                prototype.update(document)
100
            # TODO: There needs to be a 'proxy' object that holds the DBRef and hydrates
101
            # self.hydrate(prototype)
102
            return prototype
103
        return document
104
105
    def hydrate(self, target):
106
        """
107
        Args:
108
            target:
109
110
        Returns:
111
            object
112
        """
113
        if isinstance(target, DBRef):
114
            # FIXME: This needs to reference the correct collection
115
            document = self.collection(target.collection).find_one(target.id)
116
            if document:
117
                document = self.hydrate(self.objectify(target.collection, document))
118
            return document
119
        elif isinstance(target, dict):
120
            for key, value in target.items():
121
                if isinstance(value, self.ref_types):
122
                    target[key] = self.hydrate(value)
123
        elif isinstance(target, list):
124
            for i, value in enumerate(target):
125
                if isinstance(value, self.ref_types):
126
                    target[i] = self.hydrate(value)
127
128
        # return target if nothing else occurred
129
        return target
130
131
    def save(self, *args):
132
        """
133
        Args:
134
            *args: One or more documents
135
136
        Returns:
137
138
        """
139
        for document in args:
140
            self.collection(document).save(document)
141
142
    def refresh(self, *args):
143
        """
144
        Args:
145
            *args: One or more documents
146
147
        Returns:
148
149
        """
150
        for document in args:
151
            self.collection(document).refresh(document)
152
153
    def remove(self, *args):
154
        """
155
        Args:
156
            *args: One or more documents
157
        """
158
        for document in args:
159
            self.collection(document).remove(document)
160
161
    def shutdown(self):
162
        """
163
        Returns:
164
165
        """
166
        pass
167