Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 184 lines (143 sloc) 6.18 kb
aec685b @behackett Fix up copyright dates.
behackett authored
1 # Copyright 2009-2015 MongoDB, Inc.
88a62b0 license
Mike Dirolf authored
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
a88554c doc
Mike Dirolf authored
15 """Manipulators that can edit SON objects as they enter and exit a database.
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
16
17 New manipulators should be defined as subclasses of SONManipulator and can be
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
18 installed on a database by calling
19 `pymongo.database.Database.add_son_manipulator`."""
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
20
17fb3a2 @llvtt PYTHON-505 Allow C extensions to encode any mapping type, not just di…
llvtt authored
21 import collections
22
9c18280 Create a separate bson package PYTHON-60
Mike Dirolf authored
23 from bson.dbref import DBRef
24 from bson.objectid import ObjectId
25 from bson.son import SON
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
26
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
27
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
28 class SONManipulator(object):
29 """A base son manipulator.
30
31 This manipulator just saves and restores objects without changing them.
32 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
33
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
34 def will_copy(self):
35 """Will this SON manipulator make a copy of the incoming document?
36
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
37 Derived classes that do need to make a copy should override this
38 method, returning True instead of False. All non-copying manipulators
39 will be applied first (so that the user's document will be updated
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
40 appropriately), followed by copying manipulators.
41 """
42 return False
43
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
44 def transform_incoming(self, son, collection):
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
45 """Manipulate an incoming SON object.
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
46
0462726 documentation: use epydoc format for rST parameter lists
Mike Dirolf authored
47 :Parameters:
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
48 - `son`: the SON object to be inserted into the database
0462726 documentation: use epydoc format for rST parameter lists
Mike Dirolf authored
49 - `collection`: the collection the object is being inserted into
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
50 """
b57d8c2 SONManipulator for converting between DBRefs and the corresponding em…
Mike Dirolf authored
51 if self.will_copy():
52 return SON(son)
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
53 return son
54
55 def transform_outgoing(self, son, collection):
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
56 """Manipulate an outgoing SON object.
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
57
0462726 documentation: use epydoc format for rST parameter lists
Mike Dirolf authored
58 :Parameters:
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
59 - `son`: the SON object being retrieved from the database
0462726 documentation: use epydoc format for rST parameter lists
Mike Dirolf authored
60 - `collection`: the collection this object was stored in
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
61 """
b57d8c2 SONManipulator for converting between DBRefs and the corresponding em…
Mike Dirolf authored
62 if self.will_copy():
63 return SON(son)
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
64 return son
65
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
66
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
67 class ObjectIdInjector(SONManipulator):
68 """A son manipulator that adds the _id field if it is missing.
9a7b748 @ajdavis Don't add _id to update documents when manipulate=True. PYTHON-585
ajdavis authored
69
4082e4c @behackett Minor docs update.
behackett authored
70 .. versionchanged:: 2.7
9a7b748 @ajdavis Don't add _id to update documents when manipulate=True. PYTHON-585
ajdavis authored
71 ObjectIdInjector is no longer used by PyMongo, but remains in this
72 module for backwards compatibility.
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
73 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
74
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
75 def transform_incoming(self, son, collection):
76 """Add an _id field if it is missing.
77 """
84acf3b _id can be anything. this hasn't been well tested yet.
Mike Dirolf authored
78 if not "_id" in son:
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
79 son["_id"] = ObjectId()
80 return son
81
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
82
45b9b78 shuffle _id to front in encoder rather than as a SONManipulator. also…
Mike Dirolf authored
83 # This is now handled during BSON encoding (for performance reasons),
84 # but I'm keeping this here as a reference for those implementing new
85 # SONManipulators.
8e7952a _id goes first
Mike Dirolf authored
86 class ObjectIdShuffler(SONManipulator):
87 """A son manipulator that moves _id to the first position.
88 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
89
5942f0d clean up the concept of copying vs non-copying manipulators. placehol…
Mike Dirolf authored
90 def will_copy(self):
91 """We need to copy to be sure that we are dealing with SON, not a dict.
92 """
93 return True
94
8e7952a _id goes first
Mike Dirolf authored
95 def transform_incoming(self, son, collection):
96 """Move _id to the front if it's there.
97 """
98 if not "_id" in son:
99 return son
100 transformed = SON({"_id": son["_id"]})
101 transformed.update(son)
102 return transformed
103
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
104
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
105 class NamespaceInjector(SONManipulator):
106 """A son manipulator that adds the _ns field.
107 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
108
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
109 def transform_incoming(self, son, collection):
110 """Add the _ns field to the incoming object
111 """
99f08e5 DEPRECATING method style access for several methods:
Mike Dirolf authored
112 son["_ns"] = collection.name
154c370 add son_manipulator module and some basic manipulators
Mike Dirolf authored
113 return son
0c1805f TODO
Mike Dirolf authored
114
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
115
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
116 class AutoReference(SONManipulator):
117 """Transparently reference and de-reference already saved embedded objects.
118
119 This manipulator should probably only be used when the NamespaceInjector is
120 also being used, otherwise it doesn't make too much sense - documents can
121 only be auto-referenced if they have an *_ns* field.
0f3a006 minor: doc: note on circular references
Mike Dirolf authored
122
123 NOTE: this will behave poorly if you have a circular reference.
b4cb9be Add database support to DBRefs (as )
Mike Dirolf authored
124
125 TODO: this only works for documents that are in the same database. To fix
126 this we'll need to add a DatabaseInjector that adds *_db* and then make
127 use of the optional *database* support for DBRefs.
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
128 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
129
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
130 def __init__(self, db):
21f9df0 @ajdavis Make AutoReference.__database public so Motor can access it
ajdavis authored
131 self.database = db
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
132
133 def will_copy(self):
134 """We need to copy so the user's document doesn't get transformed refs.
135 """
136 return True
137
138 def transform_incoming(self, son, collection):
139 """Replace embedded documents with DBRefs.
140 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
141
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
142 def transform_value(value):
17fb3a2 @llvtt PYTHON-505 Allow C extensions to encode any mapping type, not just di…
llvtt authored
143 if isinstance(value, collections.MutableMapping):
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
144 if "_id" in value and "_ns" in value:
145 return DBRef(value["_ns"], transform_value(value["_id"]))
146 else:
147 return transform_dict(SON(value))
d80de9c minor: remove all uses of types module
Mike Dirolf authored
148 elif isinstance(value, list):
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
149 return [transform_value(v) for v in value]
150 return value
151
152 def transform_dict(object):
153 for (key, value) in object.items():
154 object[key] = transform_value(value)
155 return object
156
157 return transform_dict(SON(son))
158
159 def transform_outgoing(self, son, collection):
160 """Replace DBRefs with embedded documents.
161 """
b8b4a04 PEP 8 - no functional changes
Mike Dirolf authored
162
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
163 def transform_value(value):
164 if isinstance(value, DBRef):
21f9df0 @ajdavis Make AutoReference.__database public so Motor can access it
ajdavis authored
165 return self.database.dereference(value)
d80de9c minor: remove all uses of types module
Mike Dirolf authored
166 elif isinstance(value, list):
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
167 return [transform_value(v) for v in value]
17fb3a2 @llvtt PYTHON-505 Allow C extensions to encode any mapping type, not just di…
llvtt authored
168 elif isinstance(value, collections.MutableMapping):
7ddbdc5 add basic auto-ref support
Mike Dirolf authored
169 return transform_dict(SON(value))
170 return value
171
172 def transform_dict(object):
173 for (key, value) in object.items():
174 object[key] = transform_value(value)
175 return object
176
177 return transform_dict(SON(son))
178
0c1805f TODO
Mike Dirolf authored
179 # TODO make a generic translator for custom types. Take encode, decode,
180 # should_encode and should_decode functions and just encode and decode where
181 # necessary. See examples/custom_type.py for where this would be useful.
182 # Alternatively it could take a should_encode, to_binary, from_binary and
183 # binary subtype.
Something went wrong with that request. Please try again.