Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb9e036b72 | ||
|
|
f0d1563c1f | ||
|
|
fd9a8bf269 | ||
|
|
d715f5844d |
@ -508,7 +508,7 @@ def object_hook(dct, json_options=DEFAULT_JSON_OPTIONS):
|
||||
def _parse_legacy_regex(doc):
|
||||
pattern = doc["$regex"]
|
||||
# Check if this is the $regex query operator.
|
||||
if isinstance(pattern, Regex):
|
||||
if not isinstance(pattern, (str, bytes)):
|
||||
return doc
|
||||
flags = 0
|
||||
# PyMongo always adds $options but some other tools may not.
|
||||
|
||||
@ -1,6 +1,27 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Changes in Version 4.0.1
|
||||
-------------------------
|
||||
|
||||
Issues Resolved
|
||||
...............
|
||||
|
||||
Version 4.0.1 fixes a number of bugs:
|
||||
|
||||
- Fixed a bug that prevented :meth:`bson.json_util.loads` from
|
||||
decoding a document with a non-string "$regex" field (`PYTHON-3028`_).
|
||||
- Fixed a bug where a client may select a hidden/ghost or not yet initialized
|
||||
replica set member leading to unexpected "connection pool paused" errors
|
||||
(`PYTHON-3027`_).
|
||||
|
||||
See the `PyMongo 4.0.1 release notes in JIRA`_ for the list of resolved issues
|
||||
in this release.
|
||||
|
||||
.. _PYTHON-3027: https://jira.mongodb.org/browse/PYTHON-3027
|
||||
.. _PYTHON-3028: https://jira.mongodb.org/browse/PYTHON-3028
|
||||
.. _PyMongo 4.0.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=32504
|
||||
|
||||
Changes in Version 4.0
|
||||
----------------------
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
.. _handling-uuid-data-example:
|
||||
|
||||
Handling UUID Data
|
||||
@ -12,7 +13,7 @@ to MongoDB and retrieve them as native :class:`uuid.UUID` objects::
|
||||
from uuid import uuid4
|
||||
|
||||
# use the 'standard' representation for cross-language compatibility.
|
||||
client = MongoClient(uuid_representation=UuidRepresentation.STANDARD)
|
||||
client = MongoClient(uuidRepresentation='standard')
|
||||
collection = client.get_database('uuid_db').get_collection('uuid_coll')
|
||||
|
||||
# remove all documents from collection
|
||||
|
||||
@ -53,7 +53,7 @@ TEXT = "text"
|
||||
.. _text index: http://docs.mongodb.org/manual/core/index-text/
|
||||
"""
|
||||
|
||||
version_tuple = (4, 0, 1, '.dev0')
|
||||
version_tuple = (4, 0, 1)
|
||||
|
||||
def get_version_string():
|
||||
if isinstance(version_tuple[-1], str):
|
||||
|
||||
@ -325,9 +325,9 @@ class MongoClient(common.BaseObject):
|
||||
speed. 9 is best compression. Defaults to -1.
|
||||
- `uuidRepresentation`: The BSON representation to use when encoding
|
||||
from and decoding to instances of :class:`~uuid.UUID`. Valid
|
||||
values are `pythonLegacy`, `javaLegacy`, `csharpLegacy`, `standard`
|
||||
and `unspecified` (the default). New applications
|
||||
should consider setting this to `standard` for cross language
|
||||
values are the strings: "standard", "pythonLegacy", "javaLegacy",
|
||||
"csharpLegacy", and "unspecified" (the default). New applications
|
||||
should consider setting this to "standard" for cross language
|
||||
compatibility. See :ref:`handling-uuid-data-example` for details.
|
||||
- `unicode_decode_error_handler`: The error handler to apply when
|
||||
a Unicode-related error occurs during BSON decoding that would
|
||||
|
||||
@ -263,9 +263,10 @@ class TopologyDescription(object):
|
||||
selector.min_wire_version,
|
||||
common_wv))
|
||||
|
||||
if self.topology_type in (TOPOLOGY_TYPE.Single,
|
||||
TOPOLOGY_TYPE.LoadBalanced,
|
||||
TOPOLOGY_TYPE.Unknown):
|
||||
if self.topology_type == TOPOLOGY_TYPE.Unknown:
|
||||
return []
|
||||
elif self.topology_type in (TOPOLOGY_TYPE.Single,
|
||||
TOPOLOGY_TYPE.LoadBalanced):
|
||||
# Ignore selectors for standalone and load balancer mode.
|
||||
return self.known_servers
|
||||
elif address:
|
||||
|
||||
2
setup.py
2
setup.py
@ -36,7 +36,7 @@ except ImportError:
|
||||
except ImportError:
|
||||
_HAVE_SPHINX = False
|
||||
|
||||
version = "4.0.1.dev0"
|
||||
version = "4.0.1"
|
||||
|
||||
f = open("README.rst")
|
||||
try:
|
||||
|
||||
52
test/mockupdb/test_rsghost.py
Normal file
52
test/mockupdb/test_rsghost.py
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright 2021-present MongoDB, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Test connections to RSGhost nodes."""
|
||||
|
||||
import datetime
|
||||
|
||||
from mockupdb import going, MockupDB
|
||||
from pymongo import MongoClient
|
||||
from pymongo.errors import ServerSelectionTimeoutError
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestRSGhost(unittest.TestCase):
|
||||
|
||||
def test_rsghost(self):
|
||||
rsother_response = {
|
||||
'ok': 1.0, 'ismaster': False, 'secondary': False,
|
||||
'info': 'Does not have a valid replica set config',
|
||||
'isreplicaset': True, 'maxBsonObjectSize': 16777216,
|
||||
'maxMessageSizeBytes': 48000000, 'maxWriteBatchSize': 100000,
|
||||
'localTime': datetime.datetime(2021, 11, 30, 0, 53, 4, 99000),
|
||||
'logicalSessionTimeoutMinutes': 30, 'connectionId': 3,
|
||||
'minWireVersion': 0, 'maxWireVersion': 15, 'readOnly': False}
|
||||
server = MockupDB(auto_ismaster=rsother_response)
|
||||
server.run()
|
||||
self.addCleanup(server.stop)
|
||||
# Default auto discovery yields a server selection timeout.
|
||||
with MongoClient(server.uri, serverSelectionTimeoutMS=250) as client:
|
||||
with self.assertRaises(ServerSelectionTimeoutError):
|
||||
client.test.command('ping')
|
||||
# Direct connection succeeds.
|
||||
with MongoClient(server.uri, directConnection=True) as client:
|
||||
with going(client.test.command, 'ping'):
|
||||
request = server.receives(ping=1)
|
||||
request.reply()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"topology_description": {
|
||||
"type": "Unknown",
|
||||
"servers": [
|
||||
{
|
||||
"address": "a:27017",
|
||||
"avg_rtt_ms": 5,
|
||||
"type": "RSGhost"
|
||||
}
|
||||
]
|
||||
},
|
||||
"operation": "read",
|
||||
"read_preference": {
|
||||
"mode": "Nearest"
|
||||
},
|
||||
"suitable_servers": [],
|
||||
"in_latency_window": []
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"topology_description": {
|
||||
"type": "Unknown",
|
||||
"servers": [
|
||||
{
|
||||
"address": "a:27017",
|
||||
"avg_rtt_ms": 5,
|
||||
"type": "RSGhost"
|
||||
}
|
||||
]
|
||||
},
|
||||
"operation": "write",
|
||||
"read_preference": {
|
||||
"mode": "Nearest"
|
||||
},
|
||||
"suitable_servers": [],
|
||||
"in_latency_window": []
|
||||
}
|
||||
@ -270,6 +270,15 @@ class TestJsonUtil(unittest.TestCase):
|
||||
json_util.dumps(Regex('.*', re.M | re.X),
|
||||
json_options=LEGACY_JSON_OPTIONS))
|
||||
|
||||
def test_regex_validation(self):
|
||||
non_str_types = [10, {}, []]
|
||||
docs = [{"$regex": i} for i in non_str_types]
|
||||
for doc in docs:
|
||||
self.assertEqual(doc, json_util.loads(json.dumps(doc)))
|
||||
|
||||
doc = {"$regex": ""}
|
||||
self.assertIsInstance(json_util.loads(json.dumps(doc)), Regex)
|
||||
|
||||
def test_minkey(self):
|
||||
self.round_trip({"m": MinKey()})
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ def make_server_description(server, hosts):
|
||||
return ServerDescription(clean_node(server['address']), Hello({}))
|
||||
|
||||
hello_response = {'ok': True, 'hosts': hosts}
|
||||
if server_type != "Standalone" and server_type != "Mongos":
|
||||
if server_type not in ("Standalone", "Mongos", "RSGhost"):
|
||||
hello_response['setName'] = "rs"
|
||||
|
||||
if server_type == "RSPrimary":
|
||||
@ -72,6 +72,10 @@ def make_server_description(server, hosts):
|
||||
hello_response['secondary'] = True
|
||||
elif server_type == "Mongos":
|
||||
hello_response['msg'] = 'isdbgrid'
|
||||
elif server_type == "RSGhost":
|
||||
hello_response['isreplicaset'] = True
|
||||
elif server_type == "RSArbiter":
|
||||
hello_response['arbiterOnly'] = True
|
||||
|
||||
hello_response['lastWrite'] = {
|
||||
'lastWriteDate': make_last_write_date(server)
|
||||
@ -149,7 +153,7 @@ def create_topology(scenario_def, **kwargs):
|
||||
|
||||
# Assert that descriptions match
|
||||
assert (scenario_def['topology_description']['type'] ==
|
||||
topology.description.topology_type_name)
|
||||
topology.description.topology_type_name), topology.description.topology_type_name
|
||||
|
||||
return topology
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user