mirror of
https://github.com/element-hq/synapse.git
synced 2026-08-22 14:29:55 +00:00
Accept memoryview parameters in the Rust value mapping
Synapse binds some binary values (e.g. slices of event data) as a `memoryview` rather than `bytes`/`bytearray`. The shim's `from_py` handled the latter two but not `memoryview`, so those parameters raised `TypeError: unsupported parameter type for postgres: memoryview` — e.g. persisting an event over federation (seen via `test_third_party_rules.test_on_new_event`). Accept a `memoryview` as a BYTEA parameter, copying its bytes out with `tobytes()` (the buffer protocol isn't available under the limited ABI the crate builds against). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3G4M92AmwSSZCbmtMJU3d
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
62f113f0a3
commit
57883548ce
@@ -47,7 +47,9 @@ use postgres_protocol::types::{
|
||||
int4_to_sql, int8_from_sql, int8_to_sql, text_to_sql, ArrayDimension,
|
||||
};
|
||||
use pyo3::exceptions::{PyTypeError, PyValueError};
|
||||
use pyo3::types::{PyBool, PyByteArray, PyBytes, PyFloat, PyInt, PyList, PyString, PyTuple};
|
||||
use pyo3::types::{
|
||||
PyBool, PyByteArray, PyBytes, PyFloat, PyInt, PyList, PyMemoryView, PyString, PyTuple,
|
||||
};
|
||||
use pyo3::{prelude::*, BoundObject};
|
||||
use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, Kind, ToSql, Type, WrongType};
|
||||
|
||||
@@ -107,6 +109,14 @@ impl PgValue {
|
||||
if let Ok(b) = obj.cast::<PyByteArray>() {
|
||||
return Ok(PgValue::Bytea(b.to_vec().into()));
|
||||
}
|
||||
// A `memoryview` (most often over binary event data) is also bound as
|
||||
// BYTEA. The buffer protocol isn't available under the limited ABI, so
|
||||
// copy its bytes out via `tobytes()`.
|
||||
if let Ok(mv) = obj.cast::<PyMemoryView>() {
|
||||
let raw = mv.call_method0("tobytes")?;
|
||||
let bytes = raw.cast::<PyBytes>()?;
|
||||
return Ok(PgValue::Bytea(bytes.as_bytes().into()));
|
||||
}
|
||||
// A list is bound as a Postgres array (for `= ANY($1)` / `!= ALL($1)`).
|
||||
// Each element is classified recursively.
|
||||
if let Ok(list) = obj.cast::<PyList>() {
|
||||
@@ -623,6 +633,13 @@ mod tests {
|
||||
PgValue::Bytea(b) => assert_eq!(&*b, b"\x00\xff"),
|
||||
other => panic!("expected Bytea, got {other:?}"),
|
||||
}
|
||||
|
||||
// A `memoryview` over bytes binds as BYTEA via the buffer protocol.
|
||||
let memoryview = py.eval(c"memoryview(b'\\x00\\xff')", None, None).unwrap();
|
||||
match PgValue::from_py(&memoryview).unwrap() {
|
||||
PgValue::Bytea(b) => assert_eq!(&*b, b"\x00\xff"),
|
||||
other => panic!("expected Bytea, got {other:?}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user