Merge branch 'master' into PYTHON-5572
This commit is contained in:
commit
8cb4ea5b10
@ -47,13 +47,13 @@ if [ -f $HOME/.visualStudioEnv.sh ]; then
|
||||
SSH_TTY=1 source $HOME/.visualStudioEnv.sh
|
||||
set -u
|
||||
fi
|
||||
uv sync --frozen
|
||||
uv sync
|
||||
|
||||
echo "Setting up python environment... done."
|
||||
|
||||
# Ensure there is a pre-commit hook if there is a git checkout.
|
||||
if [ -d .git ] && [ ! -f .git/hooks/pre-commit ]; then
|
||||
uv run --frozen pre-commit install
|
||||
uv run pre-commit install
|
||||
fi
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
@ -105,12 +105,6 @@ repos:
|
||||
# - test/test_client.py:188: te ==> the, be, we, to
|
||||
args: ["-L", "fle,fo,infinit,isnt,nin,te,aks"]
|
||||
|
||||
- repo: https://github.com/astral-sh/uv-pre-commit
|
||||
# uv version.
|
||||
rev: 0.8.17
|
||||
hooks:
|
||||
- id: uv-lock
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: executable-shell
|
||||
@ -128,3 +122,14 @@ repos:
|
||||
language: python
|
||||
require_serial: true
|
||||
additional_dependencies: ["shrub.py>=3.10.0", "pyyaml>=6.0.2"]
|
||||
|
||||
- id: uv-lock
|
||||
name: uv-lock
|
||||
entry: uv lock
|
||||
language: python
|
||||
require_serial: true
|
||||
files: ^(uv\.lock|pyproject\.toml|requirements.txt|requirements/.*\.txt)$
|
||||
pass_filenames: false
|
||||
fail_fast: true
|
||||
additional_dependencies:
|
||||
- "uv>=0.8.4"
|
||||
|
||||
@ -1009,7 +1009,7 @@ def _dict_to_bson(
|
||||
try:
|
||||
elements.append(_element_to_bson(key, value, check_keys, opts))
|
||||
except InvalidDocument as err:
|
||||
raise InvalidDocument(f"Invalid document {doc} | {err}") from err
|
||||
raise InvalidDocument(f"Invalid document: {err}", doc) from err
|
||||
except AttributeError:
|
||||
raise TypeError(f"encoder expected a mapping type but got: {doc!r}") from None
|
||||
|
||||
|
||||
@ -1645,11 +1645,11 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
/* Update Invalid Document error message to include doc.
|
||||
/* Update Invalid Document error to include doc as a property.
|
||||
*/
|
||||
void handle_invalid_doc_error(PyObject* dict) {
|
||||
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
||||
PyObject *msg = NULL, *dict_str = NULL, *new_msg = NULL;
|
||||
PyObject *msg = NULL, *new_msg = NULL, *new_evalue = NULL;
|
||||
PyErr_Fetch(&etype, &evalue, &etrace);
|
||||
PyObject *InvalidDocument = _error("InvalidDocument");
|
||||
if (InvalidDocument == NULL) {
|
||||
@ -1659,26 +1659,22 @@ void handle_invalid_doc_error(PyObject* dict) {
|
||||
if (evalue && PyErr_GivenExceptionMatches(etype, InvalidDocument)) {
|
||||
PyObject *msg = PyObject_Str(evalue);
|
||||
if (msg) {
|
||||
// Prepend doc to the existing message
|
||||
PyObject *dict_str = PyObject_Str(dict);
|
||||
if (dict_str == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
const char * dict_str_utf8 = PyUnicode_AsUTF8(dict_str);
|
||||
if (dict_str_utf8 == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
const char * msg_utf8 = PyUnicode_AsUTF8(msg);
|
||||
if (msg_utf8 == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
PyObject *new_msg = PyUnicode_FromFormat("Invalid document %s | %s", dict_str_utf8, msg_utf8);
|
||||
PyObject *new_msg = PyUnicode_FromFormat("Invalid document: %s", msg_utf8);
|
||||
if (new_msg == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
// Add doc to the error instance as a property.
|
||||
PyObject *new_evalue = PyObject_CallFunctionObjArgs(InvalidDocument, new_msg, dict, NULL);
|
||||
Py_DECREF(evalue);
|
||||
Py_DECREF(etype);
|
||||
etype = InvalidDocument;
|
||||
InvalidDocument = NULL;
|
||||
if (new_msg) {
|
||||
evalue = new_msg;
|
||||
if (new_evalue) {
|
||||
evalue = new_evalue;
|
||||
} else {
|
||||
evalue = msg;
|
||||
}
|
||||
@ -1689,7 +1685,7 @@ cleanup:
|
||||
PyErr_Restore(etype, evalue, etrace);
|
||||
Py_XDECREF(msg);
|
||||
Py_XDECREF(InvalidDocument);
|
||||
Py_XDECREF(dict_str);
|
||||
Py_XDECREF(new_evalue);
|
||||
Py_XDECREF(new_msg);
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
"""Exceptions raised by the BSON package."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class BSONError(Exception):
|
||||
"""Base class for all BSON exceptions."""
|
||||
@ -31,6 +33,17 @@ class InvalidStringData(BSONError):
|
||||
class InvalidDocument(BSONError):
|
||||
"""Raised when trying to create a BSON object from an invalid document."""
|
||||
|
||||
def __init__(self, message: str, document: Optional[Any] = None) -> None:
|
||||
super().__init__(message)
|
||||
self._document = document
|
||||
|
||||
@property
|
||||
def document(self) -> Any:
|
||||
"""The invalid document that caused the error.
|
||||
|
||||
..versionadded:: 4.16"""
|
||||
return self._document
|
||||
|
||||
|
||||
class InvalidId(BSONError):
|
||||
"""Raised when trying to create an ObjectId from invalid data."""
|
||||
|
||||
@ -1,6 +1,15 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Changes in Version 4.16.0 (XXXX/XX/XX)
|
||||
--------------------------------------
|
||||
|
||||
PyMongo 4.16 brings a number of changes including:
|
||||
|
||||
- Removed invalid documents from :class:`bson.errors.InvalidDocument` error messages as
|
||||
doing so may leak sensitive user data.
|
||||
Instead, invalid documents are stored in :attr:`bson.errors.InvalidDocument.document`.
|
||||
|
||||
Changes in Version 4.15.1 (2025/09/16)
|
||||
--------------------------------------
|
||||
|
||||
|
||||
4
justfile
4
justfile
@ -1,7 +1,5 @@
|
||||
# See https://just.systems/man/en/ for instructions
|
||||
set shell := ["bash", "-c"]
|
||||
# Do not modify the lock file when running justfile commands.
|
||||
export UV_FROZEN := "1"
|
||||
|
||||
# Commonly used command segments.
|
||||
typing_run := "uv run --group typing --extra aws --extra encryption --extra ocsp --extra snappy --extra test --extra zstd"
|
||||
@ -16,7 +14,7 @@ default:
|
||||
|
||||
[private]
|
||||
resync:
|
||||
@uv sync --quiet --frozen
|
||||
@uv sync --quiet
|
||||
|
||||
install:
|
||||
bash .evergreen/scripts/setup-dev-env.sh
|
||||
|
||||
@ -1163,7 +1163,7 @@ class TestBSON(unittest.TestCase):
|
||||
):
|
||||
encode({"t": Wrapper(1)})
|
||||
|
||||
def test_doc_in_invalid_document_error_message(self):
|
||||
def test_doc_in_invalid_document_error_as_property(self):
|
||||
class Wrapper:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
@ -1173,10 +1173,11 @@ class TestBSON(unittest.TestCase):
|
||||
|
||||
self.assertEqual("1", repr(Wrapper(1)))
|
||||
doc = {"t": Wrapper(1)}
|
||||
with self.assertRaisesRegex(InvalidDocument, f"Invalid document {doc}"):
|
||||
with self.assertRaisesRegex(InvalidDocument, "Invalid document:") as cm:
|
||||
encode(doc)
|
||||
self.assertEqual(cm.exception.document, doc)
|
||||
|
||||
def test_doc_in_invalid_document_error_message_mapping(self):
|
||||
def test_doc_in_invalid_document_error_as_property_mapping(self):
|
||||
class MyMapping(abc.Mapping):
|
||||
def keys(self):
|
||||
return ["t"]
|
||||
@ -1192,6 +1193,11 @@ class TestBSON(unittest.TestCase):
|
||||
def __iter__(self):
|
||||
return iter(["t"])
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, MyMapping):
|
||||
return True
|
||||
return False
|
||||
|
||||
class Wrapper:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
@ -1201,8 +1207,9 @@ class TestBSON(unittest.TestCase):
|
||||
|
||||
self.assertEqual("1", repr(Wrapper(1)))
|
||||
doc = MyMapping()
|
||||
with self.assertRaisesRegex(InvalidDocument, f"Invalid document {doc}"):
|
||||
with self.assertRaisesRegex(InvalidDocument, "Invalid document:") as cm:
|
||||
encode(doc)
|
||||
self.assertEqual(cm.exception.document, doc)
|
||||
|
||||
|
||||
class TestCodecOptions(unittest.TestCase):
|
||||
|
||||
2
uv.lock
generated
2
uv.lock
generated
@ -1309,7 +1309,7 @@ requires-dist = [
|
||||
{ name = "furo", marker = "extra == 'docs'", specifier = "==2025.7.19" },
|
||||
{ name = "importlib-metadata", marker = "python_full_version < '3.13' and extra == 'test'", specifier = ">=7.0" },
|
||||
{ name = "pykerberos", marker = "os_name != 'nt' and extra == 'gssapi'" },
|
||||
{ name = "pymongo-auth-aws", marker = "extra == 'aws'", specifier = ">=1.1.0,<2.0.0" },
|
||||
{ name = "pymongo-auth-aws", marker = "extra == 'aws'", specifier = ">=1.1.1,<2.0.0" },
|
||||
{ name = "pymongo-auth-aws", marker = "extra == 'encryption'", specifier = ">=1.1.0,<2.0.0" },
|
||||
{ name = "pymongocrypt", marker = "extra == 'encryption'", specifier = ">=1.13.0,<2.0.0" },
|
||||
{ name = "pyopenssl", marker = "extra == 'ocsp'", specifier = ">=17.2.0" },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user