@@ -178,7 +178,9 @@ def _socket_for_writes(self):
178178 def _command (self , sock_info , command , slave_ok = False ,
179179 read_preference = None ,
180180 codec_options = None , check = True , allowable_errors = None ,
181- read_concern = DEFAULT_READ_CONCERN ):
181+ read_concern = DEFAULT_READ_CONCERN ,
182+ write_concern = None ,
183+ parse_write_concern_error = False ):
182184 """Internal command helper.
183185
184186 :Parameters:
@@ -191,21 +193,29 @@ def _command(self, sock_info, command, slave_ok=False,
191193 - `allowable_errors`: errors to ignore if `check` is True
192194 - `read_concern` (optional) - An instance of
193195 :class:`~pymongo.read_concern.ReadConcern`.
196+ - `write_concern`: An instance of
197+ :class:`~pymongo.write_concern.WriteConcern`. This option is only
198+ valid for MongoDB 3.4 and above.
199+ - `parse_write_concern_error` (optional): Whether to parse a
200+ ``writeConcernError`` field in the command response.
194201
195202 :Returns:
196203
197204 # todo: don't return address
198205
199206 (result document, address of server the command was run on)
200207 """
201- return sock_info .command (self .__database .name ,
202- command ,
203- slave_ok ,
204- read_preference or self .read_preference ,
205- codec_options or self .codec_options ,
206- check ,
207- allowable_errors ,
208- read_concern = read_concern )
208+ return sock_info .command (
209+ self .__database .name ,
210+ command ,
211+ slave_ok ,
212+ read_preference or self .read_preference ,
213+ codec_options or self .codec_options ,
214+ check ,
215+ allowable_errors ,
216+ read_concern = read_concern ,
217+ write_concern = write_concern ,
218+ parse_write_concern_error = parse_write_concern_error )
209219
210220 def __create (self , options ):
211221 """Sends a create command with the given options.
@@ -217,7 +227,9 @@ def __create(self, options):
217227 cmd .update (options )
218228 with self ._socket_for_writes () as sock_info :
219229 self ._command (
220- sock_info , cmd , read_preference = ReadPreference .PRIMARY )
230+ sock_info , cmd , read_preference = ReadPreference .PRIMARY ,
231+ write_concern = self .write_concern ,
232+ parse_write_concern_error = True )
221233
222234 def __getattr__ (self , name ):
223235 """Get a sub-collection of this collection by name.
@@ -1268,6 +1280,13 @@ def create_indexes(self, indexes):
12681280 introduced in MongoDB **2.6** and cannot be used with earlier
12691281 versions.
12701282
1283+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1284+ this collection is automatically applied to this operation when using
1285+ MongoDB >= 3.4.
1286+
1287+ .. versionchanged:: 3.4
1288+ Apply this collection's write concern automatically to this operation
1289+ when connected to MongoDB >= 3.4.
12711290 .. versionadded:: 3.0
12721291 """
12731292 if not isinstance (indexes , list ):
@@ -1285,7 +1304,9 @@ def gen_indexes():
12851304 ('indexes' , list (gen_indexes ()))])
12861305 with self ._socket_for_writes () as sock_info :
12871306 self ._command (
1288- sock_info , cmd , read_preference = ReadPreference .PRIMARY )
1307+ sock_info , cmd , read_preference = ReadPreference .PRIMARY ,
1308+ write_concern = self .write_concern ,
1309+ parse_write_concern_error = True )
12891310 return names
12901311
12911312 def __create_index (self , keys , index_options ):
@@ -1303,7 +1324,9 @@ def __create_index(self, keys, index_options):
13031324 cmd = SON ([('createIndexes' , self .name ), ('indexes' , [index ])])
13041325 try :
13051326 self ._command (
1306- sock_info , cmd , read_preference = ReadPreference .PRIMARY )
1327+ sock_info , cmd , read_preference = ReadPreference .PRIMARY ,
1328+ write_concern = self .write_concern ,
1329+ parse_write_concern_error = True )
13071330 except OperationFailure as exc :
13081331 if exc .code in common .COMMAND_NOT_FOUND_CODES :
13091332 index ["ns" ] = self .__full_name
@@ -1374,13 +1397,20 @@ def create_index(self, keys, **kwargs):
13741397
13751398 .. note:: `partialFilterExpression` requires server version **>= 3.2**
13761399
1400+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1401+ this collection is automatically applied to this operation when using
1402+ MongoDB >= 3.4.
1403+
13771404 :Parameters:
13781405 - `keys`: a single key or a list of (key, direction)
13791406 pairs specifying the index to create
13801407 - `**kwargs` (optional): any additional index creation
13811408 options (see the above list) should be passed as keyword
13821409 arguments
13831410
1411+ .. versionchanged:: 3.4
1412+ Apply this collection's write concern automatically to this operation
1413+ when connected to MongoDB >= 3.4.
13841414 .. versionchanged:: 3.2
13851415 Added partialFilterExpression to support partial indexes.
13861416 .. versionchanged:: 3.0
@@ -1436,6 +1466,15 @@ def drop_indexes(self):
14361466
14371467 Can be used on non-existant collections or collections with no indexes.
14381468 Raises OperationFailure on an error.
1469+
1470+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1471+ this collection is automatically applied to this operation when using
1472+ MongoDB >= 3.4.
1473+
1474+ .. versionchanged:: 3.4
1475+ Apply this collection's write concern automatically to this operation
1476+ when connected to MongoDB >= 3.4.
1477+
14391478 """
14401479 self .__database .client ._purge_index (self .__database .name , self .__name )
14411480 self .drop_index ("*" )
@@ -1459,6 +1498,15 @@ def drop_index(self, index_or_name):
14591498
14601499 :Parameters:
14611500 - `index_or_name`: index (or name of index) to drop
1501+
1502+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1503+ this collection is automatically applied to this operation when using
1504+ MongoDB >= 3.4.
1505+
1506+ .. versionchanged:: 3.4
1507+ Apply this collection's write concern automatically to this operation
1508+ when connected to MongoDB >= 3.4.
1509+
14621510 """
14631511 name = index_or_name
14641512 if isinstance (index_or_name , list ):
@@ -1474,19 +1522,32 @@ def drop_index(self, index_or_name):
14741522 self ._command (sock_info ,
14751523 cmd ,
14761524 read_preference = ReadPreference .PRIMARY ,
1477- allowable_errors = ["ns not found" ])
1525+ allowable_errors = ["ns not found" ],
1526+ write_concern = self .write_concern ,
1527+ parse_write_concern_error = True )
14781528
14791529 def reindex (self ):
14801530 """Rebuilds all indexes on this collection.
14811531
14821532 .. warning:: reindex blocks all other operations (indexes
14831533 are built in the foreground) and will be slow for large
14841534 collections.
1535+
1536+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1537+ this collection is automatically applied to this operation when using
1538+ MongoDB >= 3.4.
1539+
1540+ .. versionchanged:: 3.4
1541+ Apply this collection's write concern automatically to this operation
1542+ when connected to MongoDB >= 3.4.
1543+
14851544 """
14861545 cmd = SON ([("reIndex" , self .__name )])
14871546 with self ._socket_for_writes () as sock_info :
14881547 return self ._command (
1489- sock_info , cmd , read_preference = ReadPreference .PRIMARY )
1548+ sock_info , cmd , read_preference = ReadPreference .PRIMARY ,
1549+ write_concern = self .write_concern ,
1550+ parse_write_concern_error = True )
14901551
14911552 def list_indexes (self ):
14921553 """Get a cursor over the index documents for this collection.
@@ -1625,6 +1686,10 @@ def aggregate(self, pipeline, **kwargs):
16251686 use :meth:`~pymongo.database.Database.command` instead. An
16261687 example is included in the :ref:`aggregate-examples` documentation.
16271688
1689+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1690+ this collection is automatically applied to this operation when using
1691+ MongoDB >= 3.4.
1692+
16281693 :Parameters:
16291694 - `pipeline`: a list of aggregation pipeline stages
16301695 - `**kwargs` (optional): See list of options above.
@@ -1633,6 +1698,9 @@ def aggregate(self, pipeline, **kwargs):
16331698 A :class:`~pymongo.command_cursor.CommandCursor` over the result
16341699 set.
16351700
1701+ .. versionchanged:: 3.4
1702+ Apply this collection's write concern automatically to this operation
1703+ when connected to MongoDB >= 3.4.
16361704 .. versionchanged:: 3.0
16371705 The :meth:`aggregate` method always returns a CommandCursor. The
16381706 pipeline argument must be a list.
@@ -1674,18 +1742,25 @@ def aggregate(self, pipeline, **kwargs):
16741742 if batch_size is not None :
16751743 kwargs ["cursor" ]["batchSize" ] = batch_size
16761744
1745+ dollar_out = pipeline and '$out' in pipeline [- 1 ]
1746+ if (sock_info .max_wire_version >= 5 and dollar_out and
1747+ self .write_concern ):
1748+ cmd ['writeConcern' ] = self .write_concern .document
1749+
16771750 cmd .update (kwargs )
16781751
16791752 # Apply this Collection's read concern if $out is not in the
16801753 # pipeline.
16811754 if sock_info .max_wire_version >= 4 and 'readConcern' not in cmd :
1682- if pipeline and '$out' in pipeline [- 1 ]:
1683- result = self ._command (sock_info , cmd , slave_ok )
1755+ if dollar_out :
1756+ result = self ._command (sock_info , cmd , slave_ok ,
1757+ parse_write_concern_error = True )
16841758 else :
16851759 result = self ._command (sock_info , cmd , slave_ok ,
16861760 read_concern = self .read_concern )
16871761 else :
1688- result = self ._command (sock_info , cmd , slave_ok )
1762+ result = self ._command (sock_info , cmd , slave_ok ,
1763+ parse_write_concern_error = dollar_out )
16891764
16901765 if "cursor" in result :
16911766 cursor = result ["cursor" ]
@@ -1764,6 +1839,15 @@ def rename(self, new_name, **kwargs):
17641839 - `**kwargs` (optional): additional arguments to the rename command
17651840 may be passed as keyword arguments to this helper method
17661841 (i.e. ``dropTarget=True``)
1842+
1843+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1844+ this collection is automatically applied to this operation when using
1845+ MongoDB >= 3.4.
1846+
1847+ .. versionchanged:: 3.4
1848+ Apply this collection's write concern automatically to this operation
1849+ when connected to MongoDB >= 3.4.
1850+
17671851 """
17681852 if not isinstance (new_name , string_type ):
17691853 raise TypeError ("new_name must be an "
@@ -1778,9 +1862,11 @@ def rename(self, new_name, **kwargs):
17781862
17791863 new_name = "%s.%s" % (self .__database .name , new_name )
17801864 cmd = SON ([("renameCollection" , self .__full_name ), ("to" , new_name )])
1781- cmd .update (kwargs )
17821865 with self ._socket_for_writes () as sock_info :
1783- sock_info .command ('admin' , cmd )
1866+ if sock_info .max_wire_version >= 5 and self .write_concern :
1867+ cmd ['writeConcern' ] = self .write_concern .document
1868+ cmd .update (kwargs )
1869+ sock_info .command ('admin' , cmd , parse_write_concern_error = True )
17841870
17851871 def distinct (self , key , filter = None , ** kwargs ):
17861872 """Get a list of distinct values for `key` among all documents
@@ -1848,6 +1934,14 @@ def map_reduce(self, map, reduce, out, full_response=False, **kwargs):
18481934 mapReduce on a secondary use the :meth:`inline_map_reduce` method
18491935 instead.
18501936
1937+ .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
1938+ this collection is automatically applied to this operation (if the
1939+ output is not inline) when using MongoDB >= 3.4.
1940+
1941+ .. versionchanged:: 3.4
1942+ Apply this collection's write concern automatically to this operation
1943+ when connected to MongoDB >= 3.4.
1944+
18511945 .. seealso:: :doc:`/examples/aggregation`
18521946
18531947 .. versionchanged:: 2.2
@@ -1856,6 +1950,7 @@ def map_reduce(self, map, reduce, out, full_response=False, **kwargs):
18561950 .. _map reduce command: http://docs.mongodb.org/manual/reference/command/mapReduce/
18571951
18581952 .. mongodoc:: mapreduce
1953+
18591954 """
18601955 if not isinstance (out , (string_type , collections .Mapping )):
18611956 raise TypeError ("'out' must be an instance of "
@@ -1865,17 +1960,24 @@ def map_reduce(self, map, reduce, out, full_response=False, **kwargs):
18651960 ("map" , map ),
18661961 ("reduce" , reduce ),
18671962 ("out" , out )])
1868- cmd .update (kwargs )
18691963
1964+ inline = 'inline' in cmd ['out' ]
18701965 with self ._socket_for_primary_reads () as (sock_info , slave_ok ):
1966+ if (sock_info .max_wire_version >= 5 and self .write_concern and
1967+ not inline ):
1968+ cmd ['writeConcern' ] = self .write_concern .document
1969+ cmd .update (kwargs )
18711970 if (sock_info .max_wire_version >= 4 and 'readConcern' not in cmd and
1872- 'inline' in cmd ['out' ]):
1971+ inline ):
1972+ # No need to parse 'writeConcernError' here, since the command
1973+ # is an inline map reduce.
18731974 response = self ._command (
18741975 sock_info , cmd , slave_ok , ReadPreference .PRIMARY ,
18751976 read_concern = self .read_concern )
18761977 else :
18771978 response = self ._command (
1878- sock_info , cmd , slave_ok , ReadPreference .PRIMARY )
1979+ sock_info , cmd , slave_ok , ReadPreference .PRIMARY ,
1980+ parse_write_concern_error = not inline )
18791981
18801982 if full_response or not response .get ('result' ):
18811983 return response
0 commit comments