commit python-pymongo for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pymongo for openSUSE:Factory checked in at 2021-06-01 10:33:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pymongo (Old) and /work/SRC/openSUSE:Factory/.python-pymongo.new.1898 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-pymongo" Tue Jun 1 10:33:28 2021 rev:39 rq:895918 version:3.11.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pymongo/python-pymongo.changes 2021-04-26 16:38:58.294013292 +0200 +++ /work/SRC/openSUSE:Factory/.python-pymongo.new.1898/python-pymongo.changes 2021-06-01 10:33:43.348431073 +0200 @@ -1,0 +2,7 @@ +Fri May 28 07:38:51 UTC 2021 - pgajdos@suse.com + +- version update to 3.11.4 + - Version 3.11.4 fixes a bug where a MongoClient would mistakenly attempt to + create minPoolSize connections to arbiter nodes (`PYTHON-2634`_). + +------------------------------------------------------------------- Old: ---- pymongo-3.11.3.tar.gz New: ---- pymongo-3.11.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pymongo.spec ++++++ --- /var/tmp/diff_new_pack.gGVwpa/_old 2021-06-01 10:33:43.944432088 +0200 +++ /var/tmp/diff_new_pack.gGVwpa/_new 2021-06-01 10:33:43.948432095 +0200 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-pymongo -Version: 3.11.3 +Version: 3.11.4 Release: 0 Summary: Python driver for MongoDB License: Apache-2.0 @@ -56,7 +56,7 @@ %python_expand %fdupes %{buildroot}%{$python_sitearch} %check -%python_exec setup.py test -v +%pyunittest discover -v %files %{python_files} %license LICENSE ++++++ pymongo-3.11.3.tar.gz -> pymongo-3.11.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/PKG-INFO new/pymongo-3.11.4/PKG-INFO --- old/pymongo-3.11.3/PKG-INFO 2021-02-03 03:56:53.000000000 +0100 +++ new/pymongo-3.11.4/PKG-INFO 2021-05-05 00:15:41.111389600 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pymongo -Version: 3.11.3 +Version: 3.11.4 Summary: Python driver for MongoDB http://www.mongodb.org Home-page: http://github.com/mongodb/mongo-python-driver Author: Mike Dirolf @@ -258,11 +258,11 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Database Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* -Provides-Extra: tls Provides-Extra: encryption -Provides-Extra: aws -Provides-Extra: gssapi +Provides-Extra: ocsp Provides-Extra: snappy -Provides-Extra: srv +Provides-Extra: tls Provides-Extra: zstd -Provides-Extra: ocsp +Provides-Extra: aws +Provides-Extra: srv +Provides-Extra: gssapi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/bson/_cbsonmodule.c new/pymongo-3.11.4/bson/_cbsonmodule.c --- old/pymongo-3.11.3/bson/_cbsonmodule.c 2021-02-03 01:53:34.000000000 +0100 +++ new/pymongo-3.11.4/bson/_cbsonmodule.c 2021-05-05 00:15:21.000000000 +0200 @@ -2621,7 +2621,7 @@ if (name_length > BSON_MAX_SIZE || position + name_length >= max) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { - PyErr_SetNone(InvalidBSON); + PyErr_SetString(InvalidBSON, "field name too large"); Py_DECREF(InvalidBSON); } return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/doc/changelog.rst new/pymongo-3.11.4/doc/changelog.rst --- old/pymongo-3.11.3/doc/changelog.rst 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/doc/changelog.rst 2021-05-05 00:15:21.000000000 +0200 @@ -1,6 +1,21 @@ Changelog ========= +Changes in Version 3.11.4 +------------------------- + +Issues Resolved +............... + +Version 3.11.4 fixes a bug where a MongoClient would mistakenly attempt to +create minPoolSize connections to arbiter nodes (`PYTHON-2634`_). + +See the `PyMongo 3.11.4 release notes in JIRA`_ for the list of resolved issues +in this release. + +.. _PYTHON-2634: https://jira.mongodb.org/browse/PYTHON-2452 +.. _PyMongo 3.11.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version... + Changes in Version 3.11.3 ------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/doc/conf.py new/pymongo-3.11.4/doc/conf.py --- old/pymongo-3.11.3/doc/conf.py 2021-02-03 01:53:34.000000000 +0100 +++ new/pymongo-3.11.4/doc/conf.py 2021-05-05 00:15:21.000000000 +0200 @@ -91,13 +91,6 @@ # Additional static files. html_static_path = ['static'] -# These paths are either relative to html_static_path -# or fully qualified paths (eg. https://...) -# Note: html_js_files was added in Sphinx 1.8. -html_js_files = [ - 'delighted.js', -] - # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". #html_title = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/doc/static/delighted.js new/pymongo-3.11.4/doc/static/delighted.js --- old/pymongo-3.11.3/doc/static/delighted.js 2021-01-16 00:06:11.000000000 +0100 +++ new/pymongo-3.11.4/doc/static/delighted.js 1970-01-01 01:00:00.000000000 +0100 @@ -1,22 +0,0 @@ -/* eslint-disable */ -// Delighted -!function(e,t,r,n,a){if(!e[a]){for(var i=e[a]=[],s=0;s<r.length;s++){var c=r[s];i[c]=i[c]||function(e){return function(){var t=Array.prototype.slice.call(arguments);i.push([e,t])}}(c)}i.SNIPPET_VERSION="1.0.1";var o=t.createElement("script");o.type="text/javascript",o.async=!0,o.src="https://d2yyd1h5u9mauk.cloudfront.net/integrations/web/v1/library/"+n+"/"+a+".js";var l=t.getElementsByTagName("script")[0];l.parentNode.insertBefore(o,l)}}(window,document,["survey","reset","config","init","set","get","event","identify","track","page","screen","group","alias"],"Dk30CC86ba0nATlK","delighted"); -// Segment -!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t,e){var n=document.createElement("script");n.type="text/javascript";n.async=!0;n.src="https://cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(n,a);analytics._loadOptions=e};analytics.SNIPPET_VERSION="4.1.0"; - analytics.load("aGhVvyxnPWlyP71vVl9ZjGWxAtoVGLXX"); - }}(); - -delighted.survey({ - minTimeOnPage: 180, - sampleFactor: 0.1, - properties: { - project: 'pymongo' - } -}); - -// Update Segment -analytics.page({ - path: location.pathname, - url: location.href, - project: 'pymongo' -}); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/pymongo/__init__.py new/pymongo-3.11.4/pymongo/__init__.py --- old/pymongo-3.11.3/pymongo/__init__.py 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/pymongo/__init__.py 2021-05-05 00:15:21.000000000 +0200 @@ -74,7 +74,7 @@ ALL = 2 """Profile all operations.""" -version_tuple = (3, 11, 3) +version_tuple = (3, 11, 4) def get_version_string(): if isinstance(version_tuple[-1], str): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/pymongo/topology.py new/pymongo-3.11.4/pymongo/topology.py --- old/pymongo-3.11.3/pymongo/topology.py 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/pymongo/topology.py 2021-05-05 00:15:21.000000000 +0200 @@ -430,15 +430,26 @@ ServerDescription(address, error=error), True) server.request_check() + def data_bearing_servers(self): + """Return a list of all data-bearing servers. + + This includes any server that might be selected for an operation. + """ + if self._description.topology_type == TOPOLOGY_TYPE.Single: + return self._description.known_servers + return self._description.readable_servers + def update_pool(self, all_credentials): # Remove any stale sockets and add new sockets if pool is too small. servers = [] with self._lock: - for server in self._servers.values(): - servers.append((server, server._pool.generation)) + # Only update pools for data-bearing servers. + for sd in self.data_bearing_servers(): + server = self._servers[sd.address] + servers.append((server, server.pool.generation)) for server, generation in servers: - server._pool.remove_stale_sockets(generation, all_credentials) + server.pool.remove_stale_sockets(generation, all_credentials) def close(self): """Clear pools and terminate monitors. Topology reopens on demand.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/pymongo.egg-info/PKG-INFO new/pymongo-3.11.4/pymongo.egg-info/PKG-INFO --- old/pymongo-3.11.3/pymongo.egg-info/PKG-INFO 2021-02-03 03:56:52.000000000 +0100 +++ new/pymongo-3.11.4/pymongo.egg-info/PKG-INFO 2021-05-05 00:15:40.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pymongo -Version: 3.11.3 +Version: 3.11.4 Summary: Python driver for MongoDB http://www.mongodb.org Home-page: http://github.com/mongodb/mongo-python-driver Author: Mike Dirolf @@ -258,11 +258,11 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Database Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* -Provides-Extra: tls Provides-Extra: encryption -Provides-Extra: aws -Provides-Extra: gssapi +Provides-Extra: ocsp Provides-Extra: snappy -Provides-Extra: srv +Provides-Extra: tls Provides-Extra: zstd -Provides-Extra: ocsp +Provides-Extra: aws +Provides-Extra: srv +Provides-Extra: gssapi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/pymongo.egg-info/SOURCES.txt new/pymongo-3.11.4/pymongo.egg-info/SOURCES.txt --- old/pymongo-3.11.3/pymongo.egg-info/SOURCES.txt 2021-02-03 03:56:52.000000000 +0100 +++ new/pymongo-3.11.4/pymongo.egg-info/SOURCES.txt 2021-05-05 00:15:40.000000000 +0200 @@ -121,7 +121,6 @@ doc/examples/uuid.rst doc/pydoctheme/theme.conf doc/pydoctheme/static/pydoctheme.css -doc/static/delighted.js doc/static/periodic-executor-refs.png doc/static/sidebar.js gridfs/__init__.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/pymongo.egg-info/requires.txt new/pymongo-3.11.4/pymongo.egg-info/requires.txt --- old/pymongo-3.11.3/pymongo.egg-info/requires.txt 2021-02-03 03:56:52.000000000 +0100 +++ new/pymongo-3.11.4/pymongo.egg-info/requires.txt 2021-05-05 00:15:40.000000000 +0200 @@ -17,10 +17,9 @@ python-snappy [srv] -dnspython<1.17.0,>=1.16.0 +dnspython<2.0.0,>=1.16.0 [tls] -ipaddress [zstd] zstandard diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/setup.py new/pymongo-3.11.4/setup.py --- old/pymongo-3.11.3/setup.py 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/setup.py 2021-05-05 00:15:21.000000000 +0200 @@ -39,7 +39,7 @@ except ImportError: _HAVE_SPHINX = False -version = "3.11.3" +version = "3.11.4" f = open("README.rst") try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/test/pymongo_mocks.py new/pymongo-3.11.4/test/pymongo_mocks.py --- old/pymongo-3.11.3/test/pymongo_mocks.py 2021-02-03 01:53:34.000000000 +0100 +++ new/pymongo-3.11.4/test/pymongo_mocks.py 2021-05-05 00:15:21.000000000 +0200 @@ -85,13 +85,13 @@ class MockClient(MongoClient): def __init__( self, standalones, members, mongoses, ismaster_hosts=None, - *args, **kwargs): + arbiters=None, down_hosts=None, *args, **kwargs): """A MongoClient connected to the default server, with a mock topology. - standalones, members, mongoses determine the configuration of the - topology. They are formatted like ['a:1', 'b:2']. ismaster_hosts - provides an alternative host list for the server's mocked ismaster - response; see test_connect_with_internal_ips. + standalones, members, mongoses, arbiters, and down_hosts determine the + configuration of the topology. They are formatted like ['a:1', 'b:2']. + ismaster_hosts provides an alternative host list for the server's + mocked ismaster response; see test_connect_with_internal_ips. """ self.mock_standalones = standalones[:] self.mock_members = members[:] @@ -101,6 +101,9 @@ else: self.mock_primary = None + # Hosts that should be considered an arbiter. + self.mock_arbiters = arbiters[:] if arbiters else [] + if ismaster_hosts is not None: self.mock_ismaster_hosts = ismaster_hosts else: @@ -109,7 +112,7 @@ self.mock_mongoses = mongoses[:] # Hosts that should raise socket errors. - self.mock_down_hosts = [] + self.mock_down_hosts = down_hosts[:] if down_hosts else [] # Hostname -> (min wire version, max wire version) self.mock_wire_versions = {} @@ -182,6 +185,10 @@ if self.mock_primary: response['primary'] = self.mock_primary + + if host in self.mock_arbiters: + response['arbiterOnly'] = True + response['secondary'] = False elif host in self.mock_mongoses: response = { 'ok': 1, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/test/test_bson.py new/pymongo-3.11.4/test/test_bson.py --- old/pymongo-3.11.3/test/test_bson.py 2021-02-03 01:53:34.000000000 +0100 +++ new/pymongo-3.11.4/test/test_bson.py 2021-05-05 00:15:21.000000000 +0200 @@ -373,6 +373,13 @@ with self.assertRaises(InvalidBSON, msg=msg): list(decode_file_iter(scratch)) + def test_invalid_field_name(self): + # Decode a truncated field + with self.assertRaises(InvalidBSON) as ctx: + decode(b'\x0b\x00\x00\x00\x02field\x00') + # Assert that the InvalidBSON error message is not empty. + self.assertTrue(str(ctx.exception)) + def test_data_timestamp(self): self.assertEqual({"test": Timestamp(4, 20)}, decode(b"\x13\x00\x00\x00\x11\x74\x65\x73\x74\x00\x14" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/test/test_client.py new/pymongo-3.11.4/test/test_client.py --- old/pymongo-3.11.3/test/test_client.py 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/test/test_client.py 2021-05-05 00:15:21.000000000 +0200 @@ -35,7 +35,7 @@ from bson.son import SON from bson.tz_util import utc import pymongo -from pymongo import auth, message +from pymongo import auth, message, monitoring from pymongo.common import CONNECT_TIMEOUT, _UUID_REPRESENTATIONS from pymongo.command_cursor import CommandCursor from pymongo.compression_support import _HAVE_SNAPPY, _HAVE_ZSTD @@ -58,7 +58,7 @@ from pymongo.pool import SocketInfo, _METADATA from pymongo.read_preferences import ReadPreference from pymongo.server_description import ServerDescription -from pymongo.server_selectors import (any_server_selector, +from pymongo.server_selectors import (readable_server_selector, writable_server_selector) from pymongo.server_type import SERVER_TYPE from pymongo.settings import TOPOLOGY_TYPE @@ -76,6 +76,7 @@ from test.pymongo_mocks import MockClient from test.utils import (assertRaisesExactly, connected, + CMAPListener, delay, FunctionCallRecorder, get_pool, @@ -452,21 +453,25 @@ class TestClient(IntegrationTest): - def test_max_idle_time_reaper(self): + def test_max_idle_time_reaper_default(self): with client_knobs(kill_cursor_frequency=0.1): # Assert reaper doesn't remove sockets when maxIdleTimeMS not set client = rs_or_single_client() - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) with server._pool.get_socket({}) as sock_info: pass self.assertEqual(1, len(server._pool.sockets)) self.assertTrue(sock_info in server._pool.sockets) client.close() + def test_max_idle_time_reaper_removes_stale_minPoolSize(self): + with client_knobs(kill_cursor_frequency=0.1): # Assert reaper removes idle socket and replaces it with a new one client = rs_or_single_client(maxIdleTimeMS=500, minPoolSize=1) - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) with server._pool.get_socket({}) as sock_info: pass # When the reaper runs at the same time as the get_socket, two @@ -478,11 +483,14 @@ "replace stale socket") client.close() + def test_max_idle_time_reaper_does_not_exceed_maxPoolSize(self): + with client_knobs(kill_cursor_frequency=0.1): # Assert reaper respects maxPoolSize when adding new sockets. client = rs_or_single_client(maxIdleTimeMS=500, minPoolSize=1, maxPoolSize=1) - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) with server._pool.get_socket({}) as sock_info: pass # When the reaper runs at the same time as the get_socket, @@ -494,9 +502,12 @@ "replace stale socket") client.close() + def test_max_idle_time_reaper_removes_stale(self): + with client_knobs(kill_cursor_frequency=0.1): # Assert reaper has removed idle socket and NOT replaced it client = rs_or_single_client(maxIdleTimeMS=500) - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) with server._pool.get_socket({}) as sock_info_one: pass # Assert that the pool does not close sockets prematurely. @@ -512,12 +523,14 @@ def test_min_pool_size(self): with client_knobs(kill_cursor_frequency=.1): client = rs_or_single_client() - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) self.assertEqual(0, len(server._pool.sockets)) # Assert that pool started up at minPoolSize client = rs_or_single_client(minPoolSize=10) - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) wait_until(lambda: 10 == len(server._pool.sockets), "pool initialized with 10 sockets") @@ -532,7 +545,8 @@ # Use high frequency to test _get_socket_no_auth. with client_knobs(kill_cursor_frequency=99999999): client = rs_or_single_client(maxIdleTimeMS=500) - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) with server._pool.get_socket({}) as sock_info: pass self.assertEqual(1, len(server._pool.sockets)) @@ -546,7 +560,8 @@ # Test that sockets are reused if maxIdleTimeMS is not set. client = rs_or_single_client() - server = client._get_topology().select_server(any_server_selector) + server = client._get_topology().select_server( + readable_server_selector) with server._pool.get_socket({}) as sock_info: pass self.assertEqual(1, len(server._pool.sockets)) @@ -2008,5 +2023,62 @@ self.assertIsNone(ct.get()) +class TestClientPool(MockClientTest): + + @client_context.require_connection + def test_rs_client_does_not_maintain_pool_to_arbiters(self): + listener = CMAPListener() + c = MockClient( + standalones=[], + members=['a:1', 'b:2', 'c:3', 'd:4'], + mongoses=[], + arbiters=['c:3'], # c:3 is an arbiter. + down_hosts=['d:4'], # d:4 is unreachable. + host=['a:1', 'b:2', 'c:3', 'd:4'], + replicaSet='rs', + minPoolSize=1, # minPoolSize + event_listeners=[listener], + ) + self.addCleanup(c.close) + + wait_until(lambda: len(c.nodes) == 3, 'connect') + self.assertEqual(c.address, ('a', 1)) + self.assertEqual(c.arbiters, set([('c', 3)])) + # Assert that we create 2 and only 2 pooled connections. + listener.wait_for_event(monitoring.ConnectionReadyEvent, 2) + self.assertEqual( + listener.event_count(monitoring.ConnectionCreatedEvent), 2) + # Assert that we do not create connections to arbiters. + arbiter = c._topology.get_server_by_address(('c', 3)) + self.assertFalse(arbiter.pool.sockets) + # Assert that we do not create connections to unknown servers. + arbiter = c._topology.get_server_by_address(('d', 4)) + self.assertFalse(arbiter.pool.sockets) + + @client_context.require_connection + def test_direct_client_maintains_pool_to_arbiter(self): + listener = CMAPListener() + c = MockClient( + standalones=[], + members=['a:1', 'b:2', 'c:3'], + mongoses=[], + arbiters=['c:3'], # c:3 is an arbiter. + host='c:3', + directConnection=True, + minPoolSize=1, # minPoolSize + event_listeners=[listener], + ) + self.addCleanup(c.close) + + wait_until(lambda: len(c.nodes) == 1, 'connect') + self.assertEqual(c.address, ('c', 3)) + # Assert that we create 1 pooled connection. + listener.wait_for_event(monitoring.ConnectionReadyEvent, 1) + self.assertEqual( + listener.event_count(monitoring.ConnectionCreatedEvent), 1) + arbiter = c._topology.get_server_by_address(('c', 3)) + self.assertEqual(len(arbiter.pool.sockets), 1) + + if __name__ == "__main__": unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/test/test_heartbeat_monitoring.py new/pymongo-3.11.4/test/test_heartbeat_monitoring.py --- old/pymongo-3.11.3/test/test_heartbeat_monitoring.py 2021-02-03 01:53:34.000000000 +0100 +++ new/pymongo-3.11.4/test/test_heartbeat_monitoring.py 2021-05-05 00:15:14.000000000 +0200 @@ -51,12 +51,12 @@ # monitor thread may run multiple times during the execution # of this test. wait_until( - lambda: len(listener.results) >= expected_len, + lambda: len(listener.events) >= expected_len, "publish all events") try: # zip gives us len(expected_results) pairs. - for expected, actual in zip(expected_results, listener.results): + for expected, actual in zip(expected_results, listener.events): self.assertEqual(expected, actual.__class__.__name__) self.assertEqual(actual.connection_id, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/test/test_streaming_protocol.py new/pymongo-3.11.4/test/test_streaming_protocol.py --- old/pymongo-3.11.3/test/test_streaming_protocol.py 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/test/test_streaming_protocol.py 2021-05-05 00:15:21.000000000 +0200 @@ -215,7 +215,7 @@ self.assertTrue(hb_failed_events[0].awaited) # Depending on thread scheduling, the failed heartbeat could occur on # the second or third check. - events = [type(e) for e in hb_listener.results[:4]] + events = [type(e) for e in hb_listener.events[:4]] if events == [monitoring.ServerHeartbeatStartedEvent, monitoring.ServerHeartbeatSucceededEvent, monitoring.ServerHeartbeatStartedEvent, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymongo-3.11.3/test/utils.py new/pymongo-3.11.4/test/utils.py --- old/pymongo-3.11.3/test/utils.py 2021-02-03 02:55:08.000000000 +0100 +++ new/pymongo-3.11.4/test/utils.py 2021-05-05 00:15:21.000000000 +0200 @@ -36,7 +36,7 @@ from pymongo import (MongoClient, monitoring, read_preferences) from pymongo.errors import ConfigurationError, OperationFailure -from pymongo.monitoring import _SENSITIVE_COMMANDS, ConnectionPoolListener +from pymongo.monitoring import _SENSITIVE_COMMANDS from pymongo.pool import (_CancellationContext, PoolOptions) from pymongo.read_concern import ReadConcern @@ -60,7 +60,7 @@ IMPOSSIBLE_WRITE_CONCERN = WriteConcern(w=50) -class CMAPListener(ConnectionPoolListener): +class BaseListener(object): def __init__(self): self.events = [] @@ -71,8 +71,26 @@ self.events.append(event) def event_count(self, event_type): - return len([event for event in self.events[:] - if isinstance(event, event_type)]) + return len(self.events_by_type(event_type)) + + def events_by_type(self, event_type): + """Return the matching events by event class. + + event_type can be a single class or a tuple of classes. + """ + return self.matching(lambda e: isinstance(e, event_type)) + + def matching(self, matcher): + """Return the matching events.""" + return [event for event in self.events[:] if matcher(event)] + + def wait_for_event(self, event, count): + """Wait for a number of events to be published, or fail.""" + wait_until(lambda: self.event_count(event) >= count, + 'find %s %s event(s)' % (count, event)) + + +class CMAPListener(BaseListener, monitoring.ConnectionPoolListener): def connection_created(self, event): self.add_event(event) @@ -196,25 +214,17 @@ """Listens to Server and Topology events.""" -class HeartbeatEventListener(monitoring.ServerHeartbeatListener): +class HeartbeatEventListener(BaseListener, monitoring.ServerHeartbeatListener): """Listens to only server heartbeat events.""" - def __init__(self): - self.results = [] - def started(self, event): - self.results.append(event) + self.add_event(event) def succeeded(self, event): - self.results.append(event) + self.add_event(event) def failed(self, event): - self.results.append(event) - - def matching(self, matcher): - """Return the matching events.""" - results = self.results[:] - return [event for event in results if matcher(event)] + self.add_event(event) class MockSocketInfo(object):
participants (1)
-
Source-Sync