Skip to content

Commit 564527c

Browse files
committed
Merge branch 'master' of github.com:mongodb/mongo-python-driver
2 parents 5bef533 + 0733c4d commit 564527c

22 files changed

+635
-73
lines changed

bson/binary.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import struct
1717
from dataclasses import dataclass
1818
from enum import Enum
19-
from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, Type, Union
19+
from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, Type, Union, overload
2020
from uuid import UUID
2121

2222
"""Tools for representing BSON binary data.
@@ -195,7 +195,7 @@ class UuidRepresentation:
195195

196196

197197
VECTOR_SUBTYPE = 9
198-
"""**(BETA)** BSON binary subtype for densely packed vector data.
198+
"""BSON binary subtype for densely packed vector data.
199199
200200
.. versionadded:: 4.10
201201
"""
@@ -207,7 +207,7 @@ class UuidRepresentation:
207207

208208

209209
class BinaryVectorDtype(Enum):
210-
"""**(BETA)** Datatypes of vector subtype.
210+
"""Datatypes of vector subtype.
211211
212212
:param FLOAT32: (0x27) Pack list of :class:`float` as float32
213213
:param INT8: (0x03) Pack list of :class:`int` in [-128, 127] as signed int8
@@ -229,7 +229,7 @@ class BinaryVectorDtype(Enum):
229229

230230
@dataclass
231231
class BinaryVector:
232-
"""**(BETA)** Vector of numbers along with metadata for binary interoperability.
232+
"""Vector of numbers along with metadata for binary interoperability.
233233
.. versionadded:: 4.10
234234
"""
235235

@@ -256,7 +256,7 @@ class Binary(bytes):
256256
the difference between what should be considered binary data and
257257
what should be considered a string when we encode to BSON.
258258
259-
**(BETA)** Subtype 9 provides a space-efficient representation of 1-dimensional vector data.
259+
Subtype 9 provides a space-efficient representation of 1-dimensional vector data.
260260
Its data is prepended with two bytes of metadata.
261261
The first (dtype) describes its data type, such as float32 or int8.
262262
The second (padding) prescribes the number of bits to ignore in the final byte.
@@ -278,7 +278,7 @@ class Binary(bytes):
278278
Support any bytes-like type that implements the buffer protocol.
279279
280280
.. versionchanged:: 4.10
281-
**(BETA)** Addition of vector subtype.
281+
Addition of vector subtype.
282282
"""
283283

284284
_type_marker = 5
@@ -397,14 +397,26 @@ def as_uuid(self, uuid_representation: int = UuidRepresentation.STANDARD) -> UUI
397397
f"cannot decode subtype {self.subtype} to {UUID_REPRESENTATION_NAMES[uuid_representation]}"
398398
)
399399

400+
@classmethod
401+
@overload
402+
def from_vector(cls: Type[Binary], vector: BinaryVector) -> Binary:
403+
...
404+
405+
@classmethod
406+
@overload
407+
def from_vector(
408+
cls: Type[Binary], vector: list[int, float], dtype: BinaryVectorDtype, padding: int = 0
409+
) -> Binary:
410+
...
411+
400412
@classmethod
401413
def from_vector(
402414
cls: Type[Binary],
403415
vector: Union[BinaryVector, list[int, float]],
404416
dtype: Optional[BinaryVectorDtype] = None,
405417
padding: Optional[int] = None,
406418
) -> Binary:
407-
"""**(BETA)** Create a BSON :class:`~bson.binary.Binary` of Vector subtype.
419+
"""Create a BSON :class:`~bson.binary.Binary` of Vector subtype.
408420
409421
To interpret the representation of the numbers, a data type must be included.
410422
See :class:`~bson.binary.BinaryVectorDtype` for available types and descriptions.
@@ -447,7 +459,7 @@ def from_vector(
447459
return cls(metadata + data, subtype=VECTOR_SUBTYPE)
448460

449461
def as_vector(self) -> BinaryVector:
450-
"""**(BETA)** From the Binary, create a list of numbers, along with dtype and padding.
462+
"""From the Binary, create a list of numbers, along with dtype and padding.
451463
452464
:return: BinaryVector
453465

pymongo/asynchronous/bulk.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,18 @@ def add_update(
140140
self,
141141
selector: Mapping[str, Any],
142142
update: Union[Mapping[str, Any], _Pipeline],
143-
multi: bool = False,
144-
upsert: bool = False,
143+
multi: bool,
144+
upsert: Optional[bool],
145145
collation: Optional[Mapping[str, Any]] = None,
146146
array_filters: Optional[list[Mapping[str, Any]]] = None,
147147
hint: Union[str, dict[str, Any], None] = None,
148148
sort: Optional[Mapping[str, Any]] = None,
149149
) -> None:
150150
"""Create an update document and add it to the list of ops."""
151151
validate_ok_for_update(update)
152-
cmd: dict[str, Any] = dict( # noqa: C406
153-
[("q", selector), ("u", update), ("multi", multi), ("upsert", upsert)]
154-
)
152+
cmd: dict[str, Any] = {"q": selector, "u": update, "multi": multi}
153+
if upsert is not None:
154+
cmd["upsert"] = upsert
155155
if collation is not None:
156156
self.uses_collation = True
157157
cmd["collation"] = collation
@@ -173,14 +173,16 @@ def add_replace(
173173
self,
174174
selector: Mapping[str, Any],
175175
replacement: Mapping[str, Any],
176-
upsert: bool = False,
176+
upsert: Optional[bool],
177177
collation: Optional[Mapping[str, Any]] = None,
178178
hint: Union[str, dict[str, Any], None] = None,
179179
sort: Optional[Mapping[str, Any]] = None,
180180
) -> None:
181181
"""Create a replace document and add it to the list of ops."""
182182
validate_ok_for_replace(replacement)
183-
cmd = {"q": selector, "u": replacement, "multi": False, "upsert": upsert}
183+
cmd: dict[str, Any] = {"q": selector, "u": replacement}
184+
if upsert is not None:
185+
cmd["upsert"] = upsert
184186
if collation is not None:
185187
self.uses_collation = True
186188
cmd["collation"] = collation
@@ -200,7 +202,7 @@ def add_delete(
200202
hint: Union[str, dict[str, Any], None] = None,
201203
) -> None:
202204
"""Create a delete document and add it to the list of ops."""
203-
cmd = {"q": selector, "limit": limit}
205+
cmd: dict[str, Any] = {"q": selector, "limit": limit}
204206
if collation is not None:
205207
self.uses_collation = True
206208
cmd["collation"] = collation

pymongo/asynchronous/client_bulk.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,13 @@ def __init__(
106106
self.bypass_doc_val = bypass_document_validation
107107
self.comment = comment
108108
self.verbose_results = verbose_results
109-
110109
self.ops: list[tuple[str, Mapping[str, Any]]] = []
111110
self.namespaces: list[str] = []
112111
self.idx_offset: int = 0
113112
self.total_ops: int = 0
114-
115113
self.executed = False
116-
self.uses_upsert = False
117114
self.uses_collation = False
118115
self.uses_array_filters = False
119-
self.uses_hint_update = False
120-
self.uses_hint_delete = False
121-
self.uses_sort = False
122-
123116
self.is_retryable = self.client.options.retry_writes
124117
self.retrying = False
125118
self.started_retryable_write = False
@@ -144,7 +137,7 @@ def add_update(
144137
namespace: str,
145138
selector: Mapping[str, Any],
146139
update: Union[Mapping[str, Any], _Pipeline],
147-
multi: bool = False,
140+
multi: bool,
148141
upsert: Optional[bool] = None,
149142
collation: Optional[Mapping[str, Any]] = None,
150143
array_filters: Optional[list[Mapping[str, Any]]] = None,
@@ -160,19 +153,16 @@ def add_update(
160153
"multi": multi,
161154
}
162155
if upsert is not None:
163-
self.uses_upsert = True
164156
cmd["upsert"] = upsert
165157
if array_filters is not None:
166158
self.uses_array_filters = True
167159
cmd["arrayFilters"] = array_filters
168160
if hint is not None:
169-
self.uses_hint_update = True
170161
cmd["hint"] = hint
171162
if collation is not None:
172163
self.uses_collation = True
173164
cmd["collation"] = collation
174165
if sort is not None:
175-
self.uses_sort = True
176166
cmd["sort"] = sort
177167
if multi:
178168
# A bulk_write containing an update_many is not retryable.
@@ -200,16 +190,13 @@ def add_replace(
200190
"multi": False,
201191
}
202192
if upsert is not None:
203-
self.uses_upsert = True
204193
cmd["upsert"] = upsert
205194
if hint is not None:
206-
self.uses_hint_update = True
207195
cmd["hint"] = hint
208196
if collation is not None:
209197
self.uses_collation = True
210198
cmd["collation"] = collation
211199
if sort is not None:
212-
self.uses_sort = True
213200
cmd["sort"] = sort
214201
self.ops.append(("replace", cmd))
215202
self.namespaces.append(namespace)
@@ -226,7 +213,6 @@ def add_delete(
226213
"""Create a delete document and add it to the list of ops."""
227214
cmd = {"delete": -1, "filter": selector, "multi": multi}
228215
if hint is not None:
229-
self.uses_hint_delete = True
230216
cmd["hint"] = hint
231217
if collation is not None:
232218
self.uses_collation = True

pymongo/asynchronous/monitor.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ def __init__(
149149
self._listeners = self._settings._pool_options._event_listeners
150150
self._publish = self._listeners is not None and self._listeners.enabled_for_server_heartbeat
151151
self._cancel_context: Optional[_CancellationContext] = None
152+
self._conn_id: Optional[int] = None
152153
self._rtt_monitor = _RttMonitor(
153154
topology,
154155
topology_settings,
@@ -243,6 +244,7 @@ async def _check_server(self) -> ServerDescription:
243244
244245
Returns a ServerDescription.
245246
"""
247+
self._conn_id = None
246248
start = time.monotonic()
247249
try:
248250
try:
@@ -272,6 +274,7 @@ async def _check_server(self) -> ServerDescription:
272274
awaited=awaited,
273275
durationMS=duration * 1000,
274276
failure=error,
277+
driverConnectionId=self._conn_id,
275278
message=_SDAMStatusMessage.HEARTBEAT_FAIL,
276279
)
277280
await self._reset_connection()
@@ -314,6 +317,8 @@ async def _check_once(self) -> ServerDescription:
314317
)
315318

316319
self._cancel_context = conn.cancel_context
320+
# Record the connection id so we can later attach it to the failed log message.
321+
self._conn_id = conn.id
317322
response, round_trip_time = await self._check_with_socket(conn)
318323
if not response.awaitable:
319324
self._rtt_monitor.add_sample(round_trip_time)

pymongo/operations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ def __init__(
332332
self,
333333
filter: Mapping[str, Any],
334334
replacement: Union[_DocumentType, RawBSONDocument],
335-
upsert: bool = False,
335+
upsert: Optional[bool] = None,
336336
collation: Optional[_CollationIn] = None,
337337
hint: Optional[_IndexKeyHint] = None,
338338
namespace: Optional[str] = None,
@@ -693,7 +693,7 @@ def _add_to_bulk(self, bulkobj: _AgnosticBulk) -> None:
693693
self._filter,
694694
self._doc,
695695
True,
696-
bool(self._upsert),
696+
self._upsert,
697697
collation=validate_collation_or_none(self._collation),
698698
array_filters=self._array_filters,
699699
hint=self._hint,

pymongo/synchronous/bulk.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,18 @@ def add_update(
140140
self,
141141
selector: Mapping[str, Any],
142142
update: Union[Mapping[str, Any], _Pipeline],
143-
multi: bool = False,
144-
upsert: bool = False,
143+
multi: bool,
144+
upsert: Optional[bool],
145145
collation: Optional[Mapping[str, Any]] = None,
146146
array_filters: Optional[list[Mapping[str, Any]]] = None,
147147
hint: Union[str, dict[str, Any], None] = None,
148148
sort: Optional[Mapping[str, Any]] = None,
149149
) -> None:
150150
"""Create an update document and add it to the list of ops."""
151151
validate_ok_for_update(update)
152-
cmd: dict[str, Any] = dict( # noqa: C406
153-
[("q", selector), ("u", update), ("multi", multi), ("upsert", upsert)]
154-
)
152+
cmd: dict[str, Any] = {"q": selector, "u": update, "multi": multi}
153+
if upsert is not None:
154+
cmd["upsert"] = upsert
155155
if collation is not None:
156156
self.uses_collation = True
157157
cmd["collation"] = collation
@@ -173,14 +173,16 @@ def add_replace(
173173
self,
174174
selector: Mapping[str, Any],
175175
replacement: Mapping[str, Any],
176-
upsert: bool = False,
176+
upsert: Optional[bool],
177177
collation: Optional[Mapping[str, Any]] = None,
178178
hint: Union[str, dict[str, Any], None] = None,
179179
sort: Optional[Mapping[str, Any]] = None,
180180
) -> None:
181181
"""Create a replace document and add it to the list of ops."""
182182
validate_ok_for_replace(replacement)
183-
cmd = {"q": selector, "u": replacement, "multi": False, "upsert": upsert}
183+
cmd: dict[str, Any] = {"q": selector, "u": replacement}
184+
if upsert is not None:
185+
cmd["upsert"] = upsert
184186
if collation is not None:
185187
self.uses_collation = True
186188
cmd["collation"] = collation
@@ -200,7 +202,7 @@ def add_delete(
200202
hint: Union[str, dict[str, Any], None] = None,
201203
) -> None:
202204
"""Create a delete document and add it to the list of ops."""
203-
cmd = {"q": selector, "limit": limit}
205+
cmd: dict[str, Any] = {"q": selector, "limit": limit}
204206
if collation is not None:
205207
self.uses_collation = True
206208
cmd["collation"] = collation

pymongo/synchronous/client_bulk.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,13 @@ def __init__(
106106
self.bypass_doc_val = bypass_document_validation
107107
self.comment = comment
108108
self.verbose_results = verbose_results
109-
110109
self.ops: list[tuple[str, Mapping[str, Any]]] = []
111110
self.namespaces: list[str] = []
112111
self.idx_offset: int = 0
113112
self.total_ops: int = 0
114-
115113
self.executed = False
116-
self.uses_upsert = False
117114
self.uses_collation = False
118115
self.uses_array_filters = False
119-
self.uses_hint_update = False
120-
self.uses_hint_delete = False
121-
self.uses_sort = False
122-
123116
self.is_retryable = self.client.options.retry_writes
124117
self.retrying = False
125118
self.started_retryable_write = False
@@ -144,7 +137,7 @@ def add_update(
144137
namespace: str,
145138
selector: Mapping[str, Any],
146139
update: Union[Mapping[str, Any], _Pipeline],
147-
multi: bool = False,
140+
multi: bool,
148141
upsert: Optional[bool] = None,
149142
collation: Optional[Mapping[str, Any]] = None,
150143
array_filters: Optional[list[Mapping[str, Any]]] = None,
@@ -160,19 +153,16 @@ def add_update(
160153
"multi": multi,
161154
}
162155
if upsert is not None:
163-
self.uses_upsert = True
164156
cmd["upsert"] = upsert
165157
if array_filters is not None:
166158
self.uses_array_filters = True
167159
cmd["arrayFilters"] = array_filters
168160
if hint is not None:
169-
self.uses_hint_update = True
170161
cmd["hint"] = hint
171162
if collation is not None:
172163
self.uses_collation = True
173164
cmd["collation"] = collation
174165
if sort is not None:
175-
self.uses_sort = True
176166
cmd["sort"] = sort
177167
if multi:
178168
# A bulk_write containing an update_many is not retryable.
@@ -200,16 +190,13 @@ def add_replace(
200190
"multi": False,
201191
}
202192
if upsert is not None:
203-
self.uses_upsert = True
204193
cmd["upsert"] = upsert
205194
if hint is not None:
206-
self.uses_hint_update = True
207195
cmd["hint"] = hint
208196
if collation is not None:
209197
self.uses_collation = True
210198
cmd["collation"] = collation
211199
if sort is not None:
212-
self.uses_sort = True
213200
cmd["sort"] = sort
214201
self.ops.append(("replace", cmd))
215202
self.namespaces.append(namespace)
@@ -226,7 +213,6 @@ def add_delete(
226213
"""Create a delete document and add it to the list of ops."""
227214
cmd = {"delete": -1, "filter": selector, "multi": multi}
228215
if hint is not None:
229-
self.uses_hint_delete = True
230216
cmd["hint"] = hint
231217
if collation is not None:
232218
self.uses_collation = True

0 commit comments

Comments
 (0)