@@ -182,6 +182,22 @@ def validate(option, value):
182182])
183183
184184
185+ class WriteConcern (dict ):
186+
187+ def __init__ (self , * args , ** kwargs ):
188+ """A subclass of dict that overrides __setitem__ to
189+ validate write concern options.
190+ """
191+ super (WriteConcern , self ).__init__ (* args , ** kwargs )
192+
193+ def __setitem__ (self , key , value ):
194+ if key not in SAFE_OPTIONS :
195+ raise ConfigurationError ("%s is not a valid write "
196+ "concern option." % (key ,))
197+ key , value = validate (key , value )
198+ super (WriteConcern , self ).__setitem__ (key , value )
199+
200+
185201class BaseObject (object ):
186202 """A base class that provides attributes and methods common
187203 to multiple pymongo classes.
@@ -196,7 +212,7 @@ def __init__(self, **options):
196212 self .__tag_sets = [{}]
197213 self .__secondary_acceptable_latency_ms = 15
198214 self .__safe = None
199- self .__safe_opts = {}
215+ self .__write_concern = WriteConcern ()
200216 self .__set_options (options )
201217 if (self .__read_pref == ReadPreference .PRIMARY
202218 and self .__tag_sets != [{}]
@@ -212,16 +228,14 @@ def __init__(self, **options):
212228 "but write concerns have been set making safe True. "
213229 "Please set safe to True." , UserWarning )
214230
215- def __set_safe_option (self , option , value , check = False ):
231+ def __set_safe_option (self , option , value ):
216232 """Validates and sets getlasterror options for this
217233 object (Connection, Database, Collection, etc.)
218234 """
219235 if value is None :
220- self .__safe_opts .pop (option , None )
236+ self .__write_concern .pop (option , None )
221237 else :
222- if check :
223- option , value = validate (option , value )
224- self .__safe_opts [option ] = value
238+ self .__write_concern [option ] = value
225239 self .__safe = True
226240
227241 def __set_options (self , options ):
@@ -247,6 +261,47 @@ def __set_options(self, options):
247261 else :
248262 self .__set_safe_option (option , value )
249263
264+ def __set_write_concern (self , value ):
265+ """Property setter for write_concern."""
266+ if not isinstance (value , dict ):
267+ raise ConfigurationError ("write_concern must be an "
268+ "instance of dict or a subclass." )
269+ # Make a copy here to avoid users accidentally setting the
270+ # same dict on multiple instances.
271+ wc = WriteConcern ()
272+ for k , v in value .iteritems ():
273+ # Make sure we validate each option.
274+ wc [k ] = v
275+ self .__write_concern = wc
276+
277+ def __get_write_concern (self ):
278+ """The write concern for this instance.
279+
280+ Supports dict style access for getting/setting write concern
281+ options. Valid options include w=<int/string>, wtimeout=<int>,
282+ j=<bool>, fsync=<bool>.
283+
284+ >>> c.write_concern
285+ {}
286+ >>> c.write_concern = {'w': 2, 'wtimeout': 1000}
287+ >>> c.write_concern
288+ {'wtimeout': 1000, 'w': 2}
289+ >>> c.write_concern['j'] = True
290+ >>> c.write_concern
291+ {'wtimeout': 1000, 'j': True, 'w': 2}
292+ >>> c.write_concern = {'j': True}
293+ >>> c.write_concern
294+ {'j': True}
295+
296+ .. note:: Accessing :attr:`write_concern` returns its value
297+ (a subclass of :class:`dict`), not a copy.
298+ """
299+ # To support dict style access we have to return the actual
300+ # WriteConcern here, not a copy.
301+ return self .__write_concern
302+
303+ write_concern = property (__get_write_concern , __set_write_concern )
304+
250305 def __get_slave_okay (self ):
251306 """DEPRECATED. Use `read_preference` instead.
252307
@@ -334,44 +389,61 @@ def __set_safe(self, value):
334389 safe = property (__get_safe , __set_safe )
335390
336391 def get_lasterror_options (self ):
337- """Returns a dict of the getlasterror options set
338- on this instance.
392+ """DEPRECATED: Use :attr:`write_concern` instead.
393+
394+ Returns a dict of the getlasterror options set on this instance.
339395
396+ .. versionchanged:: 2.3+
397+ Deprecated get_lasterror_options.
340398 .. versionadded:: 2.0
341399 """
342- return self .__safe_opts .copy ()
400+ warnings .warn ("get_lasterror_options is deprecated. Please use "
401+ "write_concern instead." , DeprecationWarning )
402+ return self .__write_concern .copy ()
343403
344404 def set_lasterror_options (self , ** kwargs ):
345- """Set getlasterror options for this instance .
405+ """DEPRECATED: Use :attr:`write_concern` instead .
346406
347- Valid options include j=<bool>, w=<int>, wtimeout=<int>,
407+ Set getlasterror options for this instance.
408+
409+ Valid options include j=<bool>, w=<int/string>, wtimeout=<int>,
348410 and fsync=<bool>. Implies safe=True.
349411
350412 :Parameters:
351413 - `**kwargs`: Options should be passed as keyword
352414 arguments (e.g. w=2, fsync=True)
353415
416+ .. versionchanged:: 2.3+
417+ Deprecated set_lasterror_options.
354418 .. versionadded:: 2.0
355419 """
420+ warnings .warn ("set_lasterror_options is deprecated. Please use "
421+ "write_concern instead." , DeprecationWarning )
356422 for key , value in kwargs .iteritems ():
357- self .__set_safe_option (key , value , check = True )
423+ self .__set_safe_option (key , value )
358424
359425 def unset_lasterror_options (self , * options ):
360- """Unset getlasterror options for this instance.
426+ """DEPRECATED: Use :attr:`write_concern` instead.
427+
428+ Unset getlasterror options for this instance.
361429
362430 If no options are passed unsets all getlasterror options.
363431 This does not set `safe` to False.
364432
365433 :Parameters:
366434 - `*options`: The list of options to unset.
367435
436+ .. versionchanged:: 2.3+
437+ Deprecated unset_lasterror_options.
368438 .. versionadded:: 2.0
369439 """
440+ warnings .warn ("unset_lasterror_options is deprecated. Please use "
441+ "write_concern instead." , DeprecationWarning )
370442 if len (options ):
371443 for option in options :
372- self .__safe_opts .pop (option , None )
444+ self .__write_concern .pop (option , None )
373445 else :
374- self .__safe_opts = {}
446+ self .__write_concern = WriteConcern ()
375447
376448 def _get_safe_and_lasterror_options (self , safe = None , ** options ):
377449 """Get the current safe mode and any getLastError options.
@@ -392,5 +464,5 @@ def _get_safe_and_lasterror_options(self, safe=None, **options):
392464 if safe or options :
393465 safe = True
394466 if not options :
395- options .update (self .get_lasterror_options () )
467+ options .update (self .__write_concern )
396468 return safe , options
0 commit comments