1
+ import contextlib
1
2
import threading
2
3
from contextlib import contextmanager
3
4
4
5
from pymongo .read_concern import ReadConcern
5
6
from pymongo .write_concern import WriteConcern
6
7
8
+ from mongoengine .base .fields import _no_dereference_for_field
7
9
from mongoengine .common import _import_class
8
10
from mongoengine .connection import DEFAULT_CONNECTION_NAME , get_db
9
11
from mongoengine .pymongo_support import count_documents
22
24
23
25
class MyThreadLocals (threading .local ):
24
26
def __init__ (self ):
27
+ # {DocCls: count} keeping track of classes with an active no_dereference context
25
28
self .no_dereferencing_class = {}
26
29
27
30
@@ -126,14 +129,55 @@ def __exit__(self, t, value, traceback):
126
129
self .cls ._get_collection_name = self .ori_get_collection_name
127
130
128
131
129
- class no_dereference :
132
+ @contextlib .contextmanager
133
+ def no_dereference (cls ):
130
134
"""no_dereference context manager.
131
135
132
136
Turns off all dereferencing in Documents for the duration of the context
133
137
manager::
134
138
135
139
with no_dereference(Group):
136
- Group.objects.find()
140
+ Group.objects()
141
+ """
142
+ try :
143
+ cls = cls
144
+
145
+ ReferenceField = _import_class ("ReferenceField" )
146
+ GenericReferenceField = _import_class ("GenericReferenceField" )
147
+ ComplexBaseField = _import_class ("ComplexBaseField" )
148
+
149
+ deref_fields = [
150
+ field
151
+ for name , field in cls ._fields .items ()
152
+ if isinstance (
153
+ field , (ReferenceField , GenericReferenceField , ComplexBaseField )
154
+ )
155
+ ]
156
+ no_deref_for_fields_contexts = [
157
+ _no_dereference_for_field (field ) for field in deref_fields
158
+ ]
159
+
160
+ _register_no_dereferencing_for_class (cls )
161
+
162
+ # ExitStack is just a fancy way of nesting multiple context managers into 1
163
+ with contextlib .ExitStack () as stack :
164
+ for mgr in no_deref_for_fields_contexts :
165
+ stack .enter_context (mgr )
166
+
167
+ yield None
168
+
169
+ finally :
170
+ _unregister_no_dereferencing_for_class (cls )
171
+
172
+
173
+ class no_dereference2 :
174
+ """no_dereference context manager.
175
+
176
+ Turns off all dereferencing in Documents for the duration of the context
177
+ manager::
178
+
179
+ with no_dereference(Group):
180
+ Group.objects()
137
181
"""
138
182
139
183
def __init__ (self , cls ):
@@ -148,24 +192,33 @@ def __init__(self, cls):
148
192
ComplexBaseField = _import_class ("ComplexBaseField" )
149
193
150
194
self .deref_fields = [
151
- k
152
- for k , v in self .cls ._fields .items ()
153
- if isinstance (v , (ReferenceField , GenericReferenceField , ComplexBaseField ))
195
+ field
196
+ for name , field in self .cls ._fields .items ()
197
+ if isinstance (
198
+ field , (ReferenceField , GenericReferenceField , ComplexBaseField )
199
+ )
200
+ ]
201
+ self .no_deref_for_fields_contexts = [
202
+ _no_dereference_for_field (field ) for field in self .deref_fields
154
203
]
155
204
156
205
def __enter__ (self ):
157
206
"""Change the objects default and _auto_dereference values."""
158
207
_register_no_dereferencing_for_class (self .cls )
159
208
160
- for field in self .deref_fields :
161
- self .cls ._fields [field ]._auto_dereference = False
209
+ for ndff_context in self .no_deref_for_fields_contexts :
210
+ ndff_context .__enter__ ()
211
+ # for field in self.deref_fields:
212
+ # self.cls._fields[field]._auto_dereference = False
162
213
163
214
def __exit__ (self , t , value , traceback ):
164
215
"""Reset the default and _auto_dereference values."""
165
216
_unregister_no_dereferencing_for_class (self .cls )
166
217
167
- for field in self .deref_fields :
168
- self .cls ._fields [field ]._auto_dereference = True
218
+ for ndff_context in self .no_deref_for_fields_contexts :
219
+ ndff_context .__exit__ (t , value , traceback )
220
+ # for field in self.deref_fields:
221
+ # self.cls._fields[field]._auto_dereference = True # should set initial values back
169
222
170
223
171
224
class no_sub_classes :
@@ -180,7 +233,7 @@ class no_sub_classes:
180
233
def __init__ (self , cls ):
181
234
"""Construct the no_sub_classes context manager.
182
235
183
- :param cls: the class to turn querying sub classes on
236
+ :param cls: the class to turn querying subclasses on
184
237
"""
185
238
self .cls = cls
186
239
self .cls_initial_subclasses = None
0 commit comments