Skip to content

Commit 91e6089

Browse files
committed
Merge branch 'master' of github.com:mongodb/mongo-python-driver
2 parents 7da2c35 + 7848feb commit 91e6089

File tree

9 files changed

+147
-9
lines changed

9 files changed

+147
-9
lines changed

bson/binary.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ def from_vector(
432432
raise NotImplementedError("%s not yet supported" % dtype)
433433

434434
metadata = struct.pack("<sB", dtype.value, padding)
435-
data = struct.pack(f"{len(vector)}{format_str}", *vector)
435+
data = struct.pack(f"<{len(vector)}{format_str}", *vector)
436436
return cls(metadata + data, subtype=VECTOR_SUBTYPE)
437437

438438
def as_vector(self) -> BinaryVector:
@@ -454,7 +454,7 @@ def as_vector(self) -> BinaryVector:
454454

455455
if dtype == BinaryVectorDtype.INT8:
456456
dtype_format = "b"
457-
format_string = f"{n_values}{dtype_format}"
457+
format_string = f"<{n_values}{dtype_format}"
458458
vector = list(struct.unpack_from(format_string, self, position))
459459
return BinaryVector(vector, dtype, padding)
460460

@@ -465,13 +465,16 @@ def as_vector(self) -> BinaryVector:
465465
raise ValueError(
466466
"Corrupt data. N bytes for a float32 vector must be a multiple of 4."
467467
)
468-
vector = list(struct.unpack_from(f"{n_values}f", self, position))
468+
dtype_format = "f"
469+
format_string = f"<{n_values}{dtype_format}"
470+
vector = list(struct.unpack_from(format_string, self, position))
469471
return BinaryVector(vector, dtype, padding)
470472

471473
elif dtype == BinaryVectorDtype.PACKED_BIT:
472474
# data packed as uint8
473475
dtype_format = "B"
474-
unpacked_uint8s = list(struct.unpack_from(f"{n_values}{dtype_format}", self, position))
476+
format_string = f"<{n_values}{dtype_format}"
477+
unpacked_uint8s = list(struct.unpack_from(format_string, self, position))
475478
return BinaryVector(unpacked_uint8s, dtype, padding)
476479

477480
else:

hatch.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ features = ["test"]
4343
test = "pytest -v --durations=5 --maxfail=10 {args}"
4444
test-eg = "bash ./.evergreen/run-tests.sh {args}"
4545
test-async = "pytest -v --durations=5 --maxfail=10 -m default_async {args}"
46-
test-mockupdb = ["pip install -U git+https://github.com/ajdavis/mongo-mockup-db@master", "test -m mockupdb"]
46+
test-mockupdb = ["pip install -U git+https://github.com/mongodb-labs/mongo-mockup-db@master", "test -m mockupdb"]
4747

4848
[envs.encryption]
4949
skip-install = true

pymongo/results.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,12 @@ def upserted_id(self) -> Any:
171171

172172
@property
173173
def did_upsert(self) -> bool:
174-
"""Whether or not an upsert took place."""
174+
"""Whether an upsert took place.
175+
176+
.. versionadded:: 4.9
177+
"""
175178
assert self.__raw_result is not None
176-
return len(self.__raw_result.get("upserted", {})) > 0
179+
return "upserted" in self.__raw_result
177180

178181

179182
class DeleteResult(_WriteResult):

test/asynchronous/test_client_bulk_write.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,46 @@ async def test_returns_error_if_auto_encryption_configured(self):
550550
"bulk_write does not currently support automatic encryption", context.exception._message
551551
)
552552

553+
@async_client_context.require_version_min(8, 0, 0, -24)
554+
@async_client_context.require_no_serverless
555+
async def test_upserted_result(self):
556+
client = await self.async_rs_or_single_client()
557+
558+
collection = client.db["coll"]
559+
self.addAsyncCleanup(collection.drop)
560+
await collection.drop()
561+
562+
models = []
563+
models.append(
564+
UpdateOne(
565+
namespace="db.coll",
566+
filter={"_id": "a"},
567+
update={"$set": {"x": 1}},
568+
upsert=True,
569+
)
570+
)
571+
models.append(
572+
UpdateOne(
573+
namespace="db.coll",
574+
filter={"_id": None},
575+
update={"$set": {"x": 1}},
576+
upsert=True,
577+
)
578+
)
579+
models.append(
580+
UpdateOne(
581+
namespace="db.coll",
582+
filter={"_id": None},
583+
update={"$set": {"x": 1}},
584+
)
585+
)
586+
result = await client.bulk_write(models=models, verbose_results=True)
587+
588+
self.assertEqual(result.upserted_count, 2)
589+
self.assertEqual(result.update_results[0].did_upsert, True)
590+
self.assertEqual(result.update_results[1].did_upsert, True)
591+
self.assertEqual(result.update_results[2].did_upsert, False)
592+
553593

554594
# https://github.com/mongodb/specifications/blob/master/source/client-side-operations-timeout/tests/README.md#11-multi-batch-bulkwrites
555595
class TestClientBulkWriteCSOT(AsyncIntegrationTest):

test/asynchronous/test_collection.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,19 @@ async def test_update_one(self):
14441444
self.assertRaises(InvalidOperation, lambda: result.upserted_id)
14451445
self.assertFalse(result.acknowledged)
14461446

1447+
async def test_update_result(self):
1448+
db = self.db
1449+
await db.drop_collection("test")
1450+
1451+
result = await db.test.update_one({"x": 0}, {"$inc": {"x": 1}}, upsert=True)
1452+
self.assertEqual(result.did_upsert, True)
1453+
1454+
result = await db.test.update_one({"_id": None, "x": 0}, {"$inc": {"x": 1}}, upsert=True)
1455+
self.assertEqual(result.did_upsert, True)
1456+
1457+
result = await db.test.update_one({"_id": None}, {"$inc": {"x": 1}})
1458+
self.assertEqual(result.did_upsert, False)
1459+
14471460
async def test_update_many(self):
14481461
db = self.db
14491462
await db.drop_collection("test")

test/mockupdb/test_handshake.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727

2828
from bson.objectid import ObjectId
29-
from pymongo import MongoClient
29+
from pymongo import MongoClient, has_c
3030
from pymongo import version as pymongo_version
3131
from pymongo.errors import OperationFailure
3232
from pymongo.server_api import ServerApi, ServerApiVersion
@@ -39,7 +39,11 @@ def _check_handshake_data(request):
3939
data = request["client"]
4040

4141
assert data["application"] == {"name": "my app"}
42-
assert data["driver"] == {"name": "PyMongo", "version": pymongo_version}
42+
if has_c():
43+
name = "PyMongo|c"
44+
else:
45+
name = "PyMongo"
46+
assert data["driver"] == {"name": name, "version": pymongo_version}
4347

4448
# Keep it simple, just check these fields exist.
4549
assert "os" in data

test/test_client_bulk_write.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,46 @@ def test_returns_error_if_auto_encryption_configured(self):
550550
"bulk_write does not currently support automatic encryption", context.exception._message
551551
)
552552

553+
@client_context.require_version_min(8, 0, 0, -24)
554+
@client_context.require_no_serverless
555+
def test_upserted_result(self):
556+
client = self.rs_or_single_client()
557+
558+
collection = client.db["coll"]
559+
self.addCleanup(collection.drop)
560+
collection.drop()
561+
562+
models = []
563+
models.append(
564+
UpdateOne(
565+
namespace="db.coll",
566+
filter={"_id": "a"},
567+
update={"$set": {"x": 1}},
568+
upsert=True,
569+
)
570+
)
571+
models.append(
572+
UpdateOne(
573+
namespace="db.coll",
574+
filter={"_id": None},
575+
update={"$set": {"x": 1}},
576+
upsert=True,
577+
)
578+
)
579+
models.append(
580+
UpdateOne(
581+
namespace="db.coll",
582+
filter={"_id": None},
583+
update={"$set": {"x": 1}},
584+
)
585+
)
586+
result = client.bulk_write(models=models, verbose_results=True)
587+
588+
self.assertEqual(result.upserted_count, 2)
589+
self.assertEqual(result.update_results[0].did_upsert, True)
590+
self.assertEqual(result.update_results[1].did_upsert, True)
591+
self.assertEqual(result.update_results[2].did_upsert, False)
592+
553593

554594
# https://github.com/mongodb/specifications/blob/master/source/client-side-operations-timeout/tests/README.md#11-multi-batch-bulkwrites
555595
class TestClientBulkWriteCSOT(IntegrationTest):

test/test_collection.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,19 @@ def test_update_one(self):
14291429
self.assertRaises(InvalidOperation, lambda: result.upserted_id)
14301430
self.assertFalse(result.acknowledged)
14311431

1432+
def test_update_result(self):
1433+
db = self.db
1434+
db.drop_collection("test")
1435+
1436+
result = db.test.update_one({"x": 0}, {"$inc": {"x": 1}}, upsert=True)
1437+
self.assertEqual(result.did_upsert, True)
1438+
1439+
result = db.test.update_one({"_id": None, "x": 0}, {"$inc": {"x": 1}}, upsert=True)
1440+
self.assertEqual(result.did_upsert, True)
1441+
1442+
result = db.test.update_one({"_id": None}, {"$inc": {"x": 1}})
1443+
self.assertEqual(result.did_upsert, False)
1444+
14321445
def test_update_many(self):
14331446
db = self.db
14341447
db.drop_collection("test")

test/test_results.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,28 @@ def test_update_result(self):
122122
self.assertEqual(raw_result["n"], result.matched_count)
123123
self.assertEqual(raw_result["nModified"], result.modified_count)
124124
self.assertEqual(raw_result["upserted"], result.upserted_id)
125+
self.assertEqual(result.did_upsert, True)
126+
127+
raw_result_2 = {
128+
"n": 1,
129+
"nModified": 1,
130+
"upserted": [
131+
{"index": 5, "_id": 1},
132+
],
133+
}
134+
self.repr_test(UpdateResult, raw_result_2)
135+
136+
result = UpdateResult(raw_result_2, True)
137+
self.assertEqual(result.did_upsert, True)
138+
139+
raw_result_3 = {
140+
"n": 1,
141+
"nModified": 1,
142+
}
143+
self.repr_test(UpdateResult, raw_result_3)
144+
145+
result = UpdateResult(raw_result_3, True)
146+
self.assertEqual(result.did_upsert, False)
125147

126148
result = UpdateResult(raw_result, False)
127149
self.assertEqual(raw_result, result.raw_result)

0 commit comments

Comments
 (0)