Hello community, here is the log from the commit of package python3-pymongo for openSUSE:Factory checked in at 2015-05-25 11:16:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-pymongo (Old) and /work/SRC/openSUSE:Factory/.python3-pymongo.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-pymongo" Changes: -------- --- /work/SRC/openSUSE:Factory/python3-pymongo/python3-pymongo.changes 2015-04-25 11:26:29.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python3-pymongo.new/python3-pymongo.changes 2015-05-25 11:16:52.000000000 +0200 @@ -1,0 +2,9 @@ +Mon May 25 06:23:05 UTC 2015 - [email protected] + +- update to version 3.0.2: + * Auth can fail while connecting to replset with recovering members + * ReadPreference.NEAREST can route operations to arbiters in PyMongo + 3.0 + * ReadPreference instances aren't copyable + +------------------------------------------------------------------- Old: ---- pymongo-3.0.1.tar.gz New: ---- pymongo-3.0.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-pymongo.spec ++++++ --- /var/tmp/diff_new_pack.swlpUi/_old 2015-05-25 11:16:53.000000000 +0200 +++ /var/tmp/diff_new_pack.swlpUi/_new 2015-05-25 11:16:53.000000000 +0200 @@ -17,7 +17,7 @@ Name: python3-pymongo -Version: 3.0.1 +Version: 3.0.2 Release: 0 Url: http://github.com/mongodb/mongo-python-driver Summary: Python driver for MongoDB ++++++ pymongo-3.0.1.tar.gz -> pymongo-3.0.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/PKG-INFO new/pymongo-3.0.2/PKG-INFO --- old/pymongo-3.0.1/PKG-INFO 2015-04-21 22:37:57.000000000 +0200 +++ new/pymongo-3.0.2/PKG-INFO 2015-05-12 21:28:05.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pymongo -Version: 3.0.1 +Version: 3.0.2 Summary: Python driver for MongoDB <http://www.mongodb.org> Home-page: http://github.com/mongodb/mongo-python-driver Author: Bernie Hackett diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/doc/api/bson/index.rst new/pymongo-3.0.2/doc/api/bson/index.rst --- old/pymongo-3.0.1/doc/api/bson/index.rst 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/doc/api/bson/index.rst 2015-05-12 00:51:23.000000000 +0200 @@ -16,6 +16,7 @@ codec_options dbref errors + int64 json_util max_key min_key diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/doc/api/bson/int64.rst new/pymongo-3.0.2/doc/api/bson/int64.rst --- old/pymongo-3.0.1/doc/api/bson/int64.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/pymongo-3.0.2/doc/api/bson/int64.rst 2015-05-12 00:51:23.000000000 +0200 @@ -0,0 +1,7 @@ +:mod:`int64` -- Tools for representing BSON int64 +================================================= +.. versionadded:: 3.0 + +.. automodule:: bson.int64 + :synopsis: Tools for representing BSON int64 + :members: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/doc/changelog.rst new/pymongo-3.0.2/doc/changelog.rst --- old/pymongo-3.0.1/doc/changelog.rst 2015-04-21 01:22:42.000000000 +0200 +++ new/pymongo-3.0.2/doc/changelog.rst 2015-05-12 01:11:51.000000000 +0200 @@ -1,6 +1,24 @@ Changelog ========= +Changes in Version 3.0.2 +------------------------ + +Version 3.0.2 fixes issues reported since the release of 3.0.1, most +importantly a bug that could route operations to replica set members +that are not in primary or secondary state when using +:class:`~pymongo.read_preferences.PrimaryPreferred` or +:class:`~pymongo.read_preferences.Nearest`. It is a recommended upgrade for +all users of PyMongo 3.0.x. + +Issues Resolved +............... + +See the `PyMongo 3.0.2 release notes in JIRA`_ for the list of resolved issues +in this release. + +.. _PyMongo 3.0.2 release notes in JIRA: https://jira.mongodb.org/browse/PYTHON/fixforversion/15430 + Changes in Version 3.0.1 ------------------------ @@ -424,6 +442,12 @@ attempt to convert from a BSON regular expression to a Python regular expression object. +PyMongo now decodes the int64 BSON type to :class:`~bson.int64.Int64`, a +trivial wrapper around long (in python 2.x) or int (in python 3.x). This +allows BSON int64 to be round tripped without losing type information in +python 3. Note that if you store a python long (or a python int larger than +4 bytes) it will be returned from PyMongo as :class:`~bson.int64.Int64`. + The `as_class`, `tz_aware`, and `uuid_subtype` options are removed from all BSON encoding and decoding methods. Use :class:`~bson.codec_options.CodecOptions` to configure these options. The @@ -450,6 +474,20 @@ .. _PyMongo 3.0 release notes in JIRA: https://jira.mongodb.org/browse/PYTHON/fixforversion/12501 +Changes in Version 2.8.1 +------------------------ + +Version 2.8.1 fixes a number of issues reported since the release of PyMongo +2.8. It is a recommended upgrade for all users of PyMongo 2.x. + +Issues Resolved +............... + +See the `PyMongo 2.8.1 release notes in JIRA`_ for the list of resolved issues +in this release. + +.. _PyMongo 2.8.1 release notes in JIRA: https://jira.mongodb.org/browse/PYTHON/fixforversion/15324 + Changes in Version 2.8 ---------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/doc/tools.rst new/pymongo-3.0.2/doc/tools.rst --- old/pymongo-3.0.1/doc/tools.rst 2015-04-02 00:41:30.000000000 +0200 +++ new/pymongo-3.0.2/doc/tools.rst 2015-05-08 01:13:35.000000000 +0200 @@ -107,6 +107,9 @@ project to enable using MongoDB as a backend for `beaker's <http://beaker.groovie.org/>`_ caching / session system. `The source is on github <http://github.com/bwmcadams/mongodb_beaker>`_. +* `Log4Mongo <https://github.com/log4mongo/log4mongo-python>`_ is a flexible + Python logging handler that can store logs in MongoDB using normal and capped + collections. * `MongoLog <http://github.com/puentesarrin/mongodb-log/>`_ is a Python logging handler that stores logs in MongoDB using a capped collection. * `c5t <http://bitbucket.org/percious/c5t/>`_ is a content-management system diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/__init__.py new/pymongo-3.0.2/pymongo/__init__.py --- old/pymongo-3.0.1/pymongo/__init__.py 2015-04-21 22:28:15.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/__init__.py 2015-05-12 21:21:52.000000000 +0200 @@ -70,7 +70,7 @@ ALL = 2 """Profile all operations.""" -version_tuple = (3, 0, 1) +version_tuple = (3, 0, 2) def get_version_string(): if isinstance(version_tuple[-1], str): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/command_cursor.py new/pymongo-3.0.2/pymongo/command_cursor.py --- old/pymongo-3.0.1/pymongo/command_cursor.py 2015-04-20 22:03:23.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/command_cursor.py 2015-05-12 00:51:23.000000000 +0200 @@ -147,11 +147,16 @@ def alive(self): """Does this cursor have the potential to return more data? - Even if :attr:`alive` is ``True``, :meth:`.next` can raise + Even if :attr:`alive` is ``True``, :meth:`next` can raise :exc:`StopIteration`. Best to use a for loop:: for doc in collection.aggregate(pipeline): print(doc) + + .. note:: :attr:`alive` can be True while iterating a cursor from + a failed server. In this case :attr:`alive` will return False after + :meth:`next` fails to retrieve the next batch of results from the + server. """ return bool(len(self.__data) or (not self.__killed)) @@ -172,8 +177,7 @@ return self def next(self): - """Advance the cursor. - """ + """Advance the cursor.""" if len(self.__data) or self._refresh(): coll = self.__collection return coll.database._fix_outgoing(self.__data.popleft(), coll) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/common.py new/pymongo-3.0.2/pymongo/common.py --- old/pymongo-3.0.1/pymongo/common.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/common.py 2015-05-12 00:51:23.000000000 +0200 @@ -220,6 +220,15 @@ return value +def validate_positive_float_or_zero(option, value): + """Validates that 'value' is 0 or a positive float, or can be converted to + 0 or a positive float. + """ + if value == 0 or value == "0": + return 0 + return validate_positive_float(option, value) + + def validate_timeout_or_none(option, value): """Validates a timeout specified in milliseconds returning a value in floating point seconds. @@ -393,7 +402,7 @@ 'read_preference': validate_read_preference, 'readpreference': validate_read_preference_mode, 'readpreferencetags': validate_read_preference_tags, - 'localthresholdms': validate_positive_float, + 'localthresholdms': validate_positive_float_or_zero, 'serverselectiontimeoutms': validate_timeout_or_zero, 'authmechanism': validate_auth_mechanism, 'authsource': validate_string, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/cursor.py new/pymongo-3.0.2/pymongo/cursor.py --- old/pymongo-3.0.1/pymongo/cursor.py 2015-04-20 22:03:23.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/cursor.py 2015-05-12 00:51:23.000000000 +0200 @@ -942,6 +942,12 @@ for doc in collection.find(): print(doc) + + .. note:: Even if :attr:`alive` is True, :meth:`next` can raise + :exc:`StopIteration`. :attr:`alive` can also be True while iterating + a cursor from a failed server. In this case :attr:`alive` will + return False after :meth:`next` fails to retrieve the next batch + of results from the server. """ return bool(len(self.__data) or (not self.__killed)) @@ -969,7 +975,8 @@ def __iter__(self): return self - def __next__(self): + def next(self): + """Advance the cursor.""" if self.__empty: raise StopIteration _db = self.__collection.database @@ -982,7 +989,7 @@ else: raise StopIteration - next = __next__ + __next__ = next def __enter__(self): return self diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/ismaster.py new/pymongo-3.0.2/pymongo/ismaster.py --- old/pymongo-3.0.1/pymongo/ismaster.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/ismaster.py 2015-05-12 00:51:23.000000000 +0200 @@ -112,6 +112,10 @@ return self._doc.get('maxWireVersion', common.MAX_WIRE_VERSION) @property + def election_id(self): + return self._doc.get('electionId') + + @property def is_writable(self): return self._is_writable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/mongo_client.py new/pymongo-3.0.2/pymongo/mongo_client.py --- old/pymongo-3.0.1/pymongo/mongo_client.py 2015-04-21 21:56:43.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/mongo_client.py 2015-05-12 00:51:23.000000000 +0200 @@ -555,10 +555,14 @@ @property def nodes(self): - """List of all connected servers. + """Set of all currently connected servers. - Nodes are either specified when this instance was created, - or discovered through the replica set discovery mechanism. + .. warning:: When connected to a replica set the value of :attr:`nodes` + can change over time as :class:`MongoClient`'s view of the replica + set changes. :attr:`nodes` can also be an empty set when + :class:`MongoClient` is first instantiated and hasn't yet connected + to any servers, or a network partition causes it to lose connection + to all servers. """ description = self._topology.description return frozenset(s.address for s in description.known_servers) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/read_preferences.py new/pymongo-3.0.2/pymongo/read_preferences.py --- old/pymongo-3.0.1/pymongo/read_preferences.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/read_preferences.py 2015-05-12 00:51:23.000000000 +0200 @@ -124,6 +124,19 @@ def __ne__(self, other): return not self == other + def __getstate__(self): + """Return value of object for pickling. + + Needed explicitly because __slots__() defined. + """ + return {'mode': self.__mode, 'tag_sets': self.__tag_sets} + + def __setstate__(self, value): + """Restore from pickling.""" + self.__mode = value['mode'] + self.__mongos_mode = _MONGOS_MODES[self.__mode] + self.__tag_sets = _validate_tag_sets(value['tag_sets']) + class Primary(_ServerMode): """Primary read preference. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/server_description.py new/pymongo-3.0.2/pymongo/server_description.py --- old/pymongo-3.0.1/pymongo/server_description.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/server_description.py 2015-05-12 00:51:23.000000000 +0200 @@ -32,7 +32,8 @@ '_address', '_server_type', '_all_hosts', '_tags', '_replica_set_name', '_primary', '_max_bson_size', '_max_message_size', '_max_write_batch_size', '_min_wire_version', '_max_wire_version', - '_round_trip_time', '_is_writable', '_is_readable', '_error') + '_round_trip_time', '_is_writable', '_is_readable', '_error', + '_election_id') def __init__( self, @@ -54,6 +55,7 @@ self._max_write_batch_size = ismaster.max_write_batch_size self._min_wire_version = ismaster.min_wire_version self._max_wire_version = ismaster.max_wire_version + self._election_id = ismaster.election_id self._is_writable = ismaster.is_writable self._is_readable = ismaster.is_readable self._round_trip_time = round_trip_time @@ -107,6 +109,10 @@ return self._max_wire_version @property + def election_id(self): + return self._election_id + + @property def round_trip_time(self): """The current average latency or None.""" # This override is for unittesting only! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/server_selectors.py new/pymongo-3.0.2/pymongo/server_selectors.py --- old/pymongo-3.0.1/pymongo/server_selectors.py 2015-04-20 22:03:23.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/server_selectors.py 2015-05-12 00:51:23.000000000 +0200 @@ -21,6 +21,10 @@ return server_descriptions +def readable_server_selector(server_descriptions): + return [s for s in server_descriptions if s.is_readable] + + def writable_server_selector(server_descriptions): return [s for s in server_descriptions if s.is_writable] @@ -37,7 +41,9 @@ def writable_preferred_server_selector(server_descriptions): """Like PrimaryPreferred but doesn't use tags or latency.""" - return writable_server_selector(server_descriptions) or server_descriptions + return ( + writable_server_selector(server_descriptions) or + secondary_server_selector(server_descriptions)) def single_tag_set_server_selector(tag_set, server_descriptions): @@ -47,6 +53,11 @@ A server tagged {'a': '1', 'b': '2'} matches the tag set {'a': '1'}. The empty tag set {} matches any server. + + The `server_descriptions` passed to this function should have + non-readable servers (e.g. RSGhost, RSArbiter, Unknown) filtered + out (e.g. by readable_server_selector or secondary_server_selector) + first. """ def tags_match(server_tags): for key, value in tag_set.items(): @@ -66,6 +77,11 @@ [{'a': 'value'}, {}] expresses a preference for servers tagged {'a': 'value'}, but accepts any server if none matches the first preference. + + The `server_descriptions` passed to this function should have + non-readable servers (e.g. RSGhost, RSArbiter, Unknown) filtered + out (e.g. by readable_server_selector or secondary_server_selector) + first. """ for tag_set in tag_sets: selected = single_tag_set_server_selector(tag_set, server_descriptions) @@ -79,6 +95,11 @@ """All servers with round trip times within latency_ms of the fastest one. No ServerDescription's round_trip_time can be None. + + The `server_descriptions` passed to this function should have + non-readable servers (e.g. RSGhost, RSArbiter, Unknown) filtered + out (e.g. by readable_server_selector or secondary_server_selector) + first. """ if not server_descriptions: # Avoid ValueError from min() with empty sequence. @@ -91,7 +112,7 @@ fastest = min(s.round_trip_time for s in server_descriptions) return [ s for s in server_descriptions - if (s.round_trip_time - fastest) < latency_ms / 1000.] + if (s.round_trip_time - fastest) <= latency_ms / 1000.] def secondary_with_tags_server_selector(tag_sets, server_descriptions): @@ -102,4 +123,5 @@ def member_with_tags_server_selector(tag_sets, server_descriptions): """All near-enough members matching the tag sets.""" - return tag_sets_server_selector(tag_sets, server_descriptions) + return tag_sets_server_selector( + tag_sets, readable_server_selector(server_descriptions)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/topology.py new/pymongo-3.0.2/pymongo/topology.py --- old/pymongo-3.0.1/pymongo/topology.py 2015-04-20 22:03:23.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/topology.py 2015-05-12 00:51:23.000000000 +0200 @@ -40,7 +40,8 @@ topology_description = TopologyDescription( topology_settings.get_topology_type(), topology_settings.get_server_descriptions(), - topology_settings.replica_set_name) + topology_settings.replica_set_name, + None) self._description = topology_description # Store the seed list to help diagnose errors in _error_message(). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo/topology_description.py new/pymongo-3.0.2/pymongo/topology_description.py --- old/pymongo-3.0.1/pymongo/topology_description.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/pymongo/topology_description.py 2015-05-12 00:51:23.000000000 +0200 @@ -28,7 +28,12 @@ class TopologyDescription(object): - def __init__(self, topology_type, server_descriptions, replica_set_name): + def __init__( + self, + topology_type, + server_descriptions, + replica_set_name, + max_election_id): """Represent a topology of servers. :Parameters: @@ -36,10 +41,12 @@ - `server_descriptions`: dict of (address, ServerDescription) for all seeds - `replica_set_name`: replica set name or None + - `max_election_id`: greatest electionId seen from a primary, or None """ self._topology_type = topology_type self._replica_set_name = replica_set_name self._server_descriptions = server_descriptions + self._max_election_id = max_election_id # Is PyMongo compatible with all servers' wire protocols? self._incompatible_err = None @@ -96,7 +103,11 @@ sds = dict((address, ServerDescription(address)) for address in self._server_descriptions) - return TopologyDescription(topology_type, sds, self._replica_set_name) + return TopologyDescription( + topology_type, + sds, + self._replica_set_name, + self._max_election_id) def server_descriptions(self): """Dict of (address, ServerDescription).""" @@ -112,6 +123,11 @@ return self._replica_set_name @property + def max_election_id(self): + """Greatest electionId seen from a primary, or None.""" + return self._max_election_id + + @property def known_servers(self): """List of Servers of types besides Unknown.""" return [s for s in self._server_descriptions.values() @@ -146,6 +162,7 @@ # TopologyDescription. topology_type = topology_description.topology_type set_name = topology_description.replica_set_name + max_election_id = topology_description.max_election_id server_type = server_description.server_type # Don't mutate the original dict of server descriptions; copy it. @@ -156,7 +173,11 @@ if topology_type == TOPOLOGY_TYPE.Single: # Single type never changes. - return TopologyDescription(TOPOLOGY_TYPE.Single, sds, set_name) + return TopologyDescription( + TOPOLOGY_TYPE.Single, + sds, + set_name, + max_election_id) if topology_type == TOPOLOGY_TYPE.Unknown: if server_type == SERVER_TYPE.Standalone: @@ -174,8 +195,8 @@ sds.pop(address) elif server_type == SERVER_TYPE.RSPrimary: - topology_type, set_name = _update_rs_from_primary( - sds, set_name, server_description) + topology_type, set_name, max_election_id = _update_rs_from_primary( + sds, set_name, server_description, max_election_id) elif server_type in ( SERVER_TYPE.RSSecondary, @@ -190,8 +211,8 @@ topology_type = _check_has_primary(sds) elif server_type == SERVER_TYPE.RSPrimary: - topology_type, set_name = _update_rs_from_primary( - sds, set_name, server_description) + topology_type, set_name, max_election_id = _update_rs_from_primary( + sds, set_name, server_description, max_election_id) elif server_type in ( SERVER_TYPE.RSSecondary, @@ -205,16 +226,21 @@ topology_type = _check_has_primary(sds) # Return updated copy. - return TopologyDescription(topology_type, sds, set_name) + return TopologyDescription(topology_type, sds, set_name, max_election_id) -def _update_rs_from_primary(sds, replica_set_name, server_description): +def _update_rs_from_primary( + sds, + replica_set_name, + server_description, + max_election_id): """Update topology description from a primary's ismaster response. - Pass in a dict of ServerDescriptions, current replica set name, and the - ServerDescription we are processing. + Pass in a dict of ServerDescriptions, current replica set name, the + ServerDescription we are processing, and the TopologyDescription's + max_election_id if any. - Returns (new topology type, new replica_set_name). + Returns (new topology type, new replica_set_name, new max_election_id). """ if replica_set_name is None: replica_set_name = server_description.replica_set_name @@ -223,7 +249,16 @@ # We found a primary but it doesn't have the replica_set_name # provided by the user. sds.pop(server_description.address) - return _check_has_primary(sds), replica_set_name + return _check_has_primary(sds), replica_set_name, max_election_id + + if server_description.election_id is not None: + if max_election_id and max_election_id > server_description.election_id: + # Stale primary, set to type Unknown. + address = server_description.address + sds[address] = ServerDescription(address) + return _check_has_primary(sds), replica_set_name, max_election_id + + max_election_id = server_description.election_id # We've heard from the primary. Is it the same primary as before? for server in sds.values(): @@ -247,7 +282,7 @@ # If the host list differs from the seed list, we may not have a primary # after all. - return _check_has_primary(sds), replica_set_name + return _check_has_primary(sds), replica_set_name, max_election_id def _update_rs_with_primary_from_member( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo.egg-info/PKG-INFO new/pymongo-3.0.2/pymongo.egg-info/PKG-INFO --- old/pymongo-3.0.1/pymongo.egg-info/PKG-INFO 2015-04-21 22:37:57.000000000 +0200 +++ new/pymongo-3.0.2/pymongo.egg-info/PKG-INFO 2015-05-12 21:28:05.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pymongo -Version: 3.0.1 +Version: 3.0.2 Summary: Python driver for MongoDB <http://www.mongodb.org> Home-page: http://github.com/mongodb/mongo-python-driver Author: Bernie Hackett diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/pymongo.egg-info/SOURCES.txt new/pymongo-3.0.2/pymongo.egg-info/SOURCES.txt --- old/pymongo-3.0.1/pymongo.egg-info/SOURCES.txt 2015-04-21 22:37:57.000000000 +0200 +++ new/pymongo-3.0.2/pymongo.egg-info/SOURCES.txt 2015-05-12 21:28:05.000000000 +0200 @@ -47,6 +47,7 @@ doc/api/bson/dbref.rst doc/api/bson/errors.rst doc/api/bson/index.rst +doc/api/bson/int64.rst doc/api/bson/json_util.rst doc/api/bson/max_key.rst doc/api/bson/min_key.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/setup.py new/pymongo-3.0.2/setup.py --- old/pymongo-3.0.1/setup.py 2015-04-21 22:28:25.000000000 +0200 +++ new/pymongo-3.0.2/setup.py 2015-05-12 21:21:41.000000000 +0200 @@ -26,7 +26,7 @@ from distutils.errors import DistutilsPlatformError, DistutilsExecError from distutils.core import Extension -version = "3.0.1" +version = "3.0.2" f = open("README.rst") try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/test/__init__.py new/pymongo-3.0.2/test/__init__.py --- old/pymongo-3.0.1/test/__init__.py 2015-04-21 00:04:45.000000000 +0200 +++ new/pymongo-3.0.2/test/__init__.py 2015-05-12 00:51:23.000000000 +0200 @@ -127,8 +127,13 @@ self.rs_client = pymongo.MongoClient( pair, replicaSet=self.replica_set_name) - self.nodes = set([partition_node(node) - for node in self.ismaster.get('hosts', [])]) + nodes = [partition_node(node) + for node in self.ismaster.get('hosts', [])] + nodes.extend([partition_node(node) + for node in self.ismaster.get('passives', [])]) + nodes.extend([partition_node(node) + for node in self.ismaster.get('arbiters', [])]) + self.nodes = set(nodes) self.rs_or_standalone_client = self.rs_client or self.client diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/test/test_discovery_and_monitoring.py new/pymongo-3.0.2/test/test_discovery_and_monitoring.py --- old/pymongo-3.0.1/test/test_discovery_and_monitoring.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/test/test_discovery_and_monitoring.py 2015-05-12 00:51:23.000000000 +0200 @@ -14,13 +14,13 @@ """Test the topology module.""" -import json import os import sys import threading sys.path[0:0] = [""] +from bson import json_util from pymongo import common from pymongo.topology import Topology from pymongo.topology_description import TOPOLOGY_TYPE @@ -175,7 +175,7 @@ for filename in filenames: with open(os.path.join(dirpath, filename)) as scenario_stream: - scenario_def = json.load(scenario_stream) + scenario_def = json_util.loads(scenario_stream.read()) # Construct test from scenario. new_test = create_test(scenario_def) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/test/test_mongos_load_balancing.py new/pymongo-3.0.2/test/test_mongos_load_balancing.py --- old/pymongo-3.0.1/test/test_mongos_load_balancing.py 2015-04-14 20:25:10.000000000 +0200 +++ new/pymongo-3.0.2/test/test_mongos_load_balancing.py 2015-05-12 00:51:23.000000000 +0200 @@ -75,7 +75,7 @@ # Latencies in seconds. mock_client.mock_rtts['a:1'] = 0.020 mock_client.mock_rtts['b:2'] = 0.025 - mock_client.mock_rtts['c:3'] = 0.040 + mock_client.mock_rtts['c:3'] = 0.045 return mock_client def test_lazy_connect(self): @@ -140,6 +140,7 @@ def test_local_threshold(self): client = connected(self.mock_client(localThresholdMS=30)) + self.assertEqual(30, client.local_threshold_ms) wait_until(lambda: len(client.nodes) == 3, 'connect to all mongoses') topology = client._topology @@ -147,6 +148,22 @@ self.assertEqual(set([('a', 1), ('b', 2), ('c', 3)]), writable_addresses(topology)) + # No error + client.admin.command('ismaster') + + client = connected(self.mock_client(localThresholdMS=0)) + self.assertEqual(0, client.local_threshold_ms) + # No error + client.db.command('ismaster') + # Our chosen mongos goes down. + client.kill_host('%s:%s' % next(iter(client.nodes))) + try: + client.db.command('ismaster') + except: + pass + # No error + client.db.command('ismaster') + def test_load_balancing(self): # Although the server selection JSON tests already prove that # select_servers works for sharded topologies, here we do an end-to-end @@ -167,7 +184,7 @@ self.assertEqual(set([('a', 1), ('b', 2)]), writable_addresses(topology)) - client.mock_rtts['a:1'] = 0.040 + client.mock_rtts['a:1'] = 0.045 # Discover only b is within latency window. wait_until(lambda: set([('b', 2)]) == writable_addresses(topology), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.0.1/test/test_read_preferences.py new/pymongo-3.0.2/test/test_read_preferences.py --- old/pymongo-3.0.1/test/test_read_preferences.py 2015-04-21 01:17:13.000000000 +0200 +++ new/pymongo-3.0.2/test/test_read_preferences.py 2015-05-12 00:51:23.000000000 +0200 @@ -15,8 +15,10 @@ """Test the replica_set_connection module.""" import contextlib +import copy import random import sys +import pickle sys.path[0:0] = [""] @@ -29,7 +31,8 @@ Primary, PrimaryPreferred, Secondary, SecondaryPreferred, Nearest, _ServerMode) -from pymongo.server_selectors import any_server_selector +from pymongo.server_description import ServerDescription +from pymongo.server_selectors import readable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.write_concern import WriteConcern @@ -41,10 +44,22 @@ unittest, db_user, db_pwd) -from test.utils import single_client, one, wait_until, rs_client +from test.utils import connected, single_client, one, wait_until, rs_client from test.version import Version +class TestReadPreferenceObjects(unittest.TestCase): + prefs = [Primary(), Secondary(), Nearest(tag_sets=[{'a': 1}, {'b': 2}])] + + def test_pickle(self): + for pref in self.prefs: + self.assertEqual(pref, pickle.loads(pickle.dumps(pref))) + + def test_copy(self): + for pref in self.prefs: + self.assertEqual(pref, copy.copy(pref)) + + class TestReadPreferencesBase(TestReplicaSetClientBase): def setUp(self): @@ -83,7 +98,7 @@ def assertReadsFrom(self, expected, **kwargs): c = rs_client(**kwargs) wait_until( - lambda: len(c.nodes) == self.w, + lambda: len(c.nodes - c.arbiters) == self.w, "discovered all nodes") used = self.read_from_which_kind(c) @@ -189,6 +204,33 @@ localthresholdms=666 ).local_threshold_ms) + self.assertEqual(0, rs_client( + localthresholdms=0 + ).local_threshold_ms) + + self.assertRaises(ValueError, + rs_client, + localthresholdms=-1) + + def test_zero_latency(self): + ping_times = set() + # Generate unique ping times. + while len(ping_times) < len(self.client.nodes): + ping_times.add(random.random()) + for ping_time, host in zip(ping_times, self.client.nodes): + ServerDescription._host_to_round_trip_time[host] = ping_time + try: + client = connected( + rs_client(readPreference='nearest', localThresholdMS=0)) + wait_until( + lambda: client.nodes == self.client.nodes, + "discovered all nodes") + host = self.read_from_which_host(client) + for _ in range(5): + self.assertEqual(host, self.read_from_which_host(client)) + finally: + ServerDescription._host_to_round_trip_time.clear() + def test_primary(self): self.assertReadsFrom( 'primary', read_preference=ReadPreference.PRIMARY) @@ -235,7 +277,8 @@ latencies = ', '.join( '%s: %dms' % (server.description.address, server.description.round_trip_time) - for server in c._get_topology().select_servers(any_server_selector)) + for server in c._get_topology().select_servers( + readable_server_selector)) self.assertFalse( not_used,
