From 83aa35b83ee761996a7cb84837ba4d295385533f Mon Sep 17 00:00:00 2001 From: Afonso Coutinho Date: Tue, 2 Jun 2026 17:20:43 +0100 Subject: [PATCH] fix: owner-less document query passes bare False to SQLAlchemy filter() (#1281) * fix: use SQL false() for owner-less document query (filter(False) raises in SQLAlchemy 2.x) * test: owner-less document query doesn't pass a bare False to filter --- src/tool_implementations.py | 6 +++++- tests/test_owned_document_query.py | 31 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/test_owned_document_query.py diff --git a/src/tool_implementations.py b/src/tool_implementations.py index 1ee61bf..9480fd4 100644 --- a/src/tool_implementations.py +++ b/src/tool_implementations.py @@ -90,7 +90,11 @@ def get_active_document(): def _owned_document_query(query, Document, owner: Optional[str]): if owner is None: - return query.filter(False) + # A bare Python `False` is not a valid SQL expression — SQLAlchemy 1.4 + # deprecates it and 2.0 raises ArgumentError. Use the SQL `false()` + # literal to return zero rows for an unscoped (owner-less) query. + from sqlalchemy import false + return query.filter(false()) return query.filter(Document.owner == owner) diff --git a/tests/test_owned_document_query.py b/tests/test_owned_document_query.py new file mode 100644 index 0000000..09e253e --- /dev/null +++ b/tests/test_owned_document_query.py @@ -0,0 +1,31 @@ +"""Tests for _owned_document_query owner scoping (src/tool_implementations.py).""" +from src.tool_implementations import _owned_document_query + + +class _FakeQuery: + def __init__(self): + self.filter_args = [] + + def filter(self, *args): + self.filter_args.append(args) + return self + + +class _Doc: + owner = "owner-column-sentinel" + + +def test_owner_none_does_not_pass_python_false(): + q = _FakeQuery() + _owned_document_query(q, _Doc, None) + arg = q.filter_args[-1][0] + # The old code passed the bare Python bool False, which SQLAlchemy 2.x + # rejects; the fix passes a SQL false() literal instead. + assert arg is not False + assert arg is not None + + +def test_owner_set_filters_by_owner(): + q = _FakeQuery() + _owned_document_query(q, _Doc, "alice") + assert q.filter_args, "should apply an owner filter"