Repository navigation
fix(inputlayer-py): reject value and sort-direction keywords in query/why/debug with where=/order_by= hints - #246
Merged
Merged
Conversation
… keywords with a where= hint why() on a derived relation, filtered, ordered and aggregated, now has live tests pinning each proof tree to its row. A keyword argument that is not an expression (why(View, key=1)) raised 'TypeError: Cannot compile expression'; it is now a CompileError naming where= as the way to filter.
jsam
marked this pull request as ready for review
October 4, 2026 14:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
So fix the SDKs by improving them. (Context: the messaging challenger found that kg.why is broken in the Python SDK on main today: kg.why(View, order=...) or kg.why(View, key=value) raised a TypeError, and kg.why on a derived view was reported to send an invalid '.why ?' statement, while the engine's own .why returns proof trees fine. The JS twin moved debug/why onto the same compiled QueryPlan as query in #229.)
What Changed
KnowledgeGraph._plan(used byquery,whyanddebug) no longer passes non-expression keyword arguments through as computed columns. It now raises aCompileErrorbefore anything is sent to the engine. A sort direction such asorder=Employee.id.desc()gets anorder_by=hint. A plain value such asdepartment="eng"gets awhere=lambda r: r.department == 'eng'hint when the keyword names a real column of the queried relations, and a genericwhere=/order_by=hint when it doesn't.test_compile_rules.py. For each ofquery,whyanddebug, they check the three keyword error cases (value keyword, sort keyword, keyword that names no column) and confirm nothing is executed.docs_queries_live.pyforkg.whyon the derivedReachableview. They coverwhere=,order_by=withlimit=, and acount()aggregate, and check that each row's proof-tree conclusion matches its result row. One more test checks thatkg.why(Reachable, src=1)is rejected with thewhere=hint.Risk Assessment
✅ Low: The change is small. It turns a non-Expr keyword value, which already failed with a TypeError inside the compiler, into a CompileError with a hint, so no call that worked before is broken. It also adds live and unit tests that exercise behavior.
Testing
I built the release inputlayer-server and let the build finish, as the operator asked. I started it on a disposable port with its own data directory and ran a driver script that logs every statement the SDK sends. With the head SDK, all six scenarios passed. The same script on the base-commit SDK reproduced the original TypeErrors and the invalid sort IQL reaching the engine. The SDK's live test files (docs_queries_live, compile_rules_live, subscriptions_live) passed against the same server, as did the mocked keyword tests. Afterwards I stopped the server, deleted its data directory and ran cargo clean.
Evidence: Live transcript, head SDK (rows, proof conclusions, statements sent)
Evidence: Live transcript, base-commit SDK (reproduces TypeError and invalid Dst:desc IQL)
Evidence: Live pytest run (docs_queries_live, compile_rules_live, subscriptions_live)
Evidence: Live scenario driver
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
packages/inputlayer-py/src/inputlayer/knowledge_graph.py:491- The intent nameskg.why(View, order=...)as one of the failing calls. The new check only catches plain values.OrderedColumnsubclassesExpr, sokg.why(Reachable, order=Reachable.dst.desc())(and the same call throughquery/debug) still passes theisinstance(v, Expr)branch and becomes a computed column namedorder. The compiler'sbind()then emitsOrder = Dst:desc(compile_expr turns an OrderedColumn intovar:desc). That is invalid IQL, so the call fails at the engine with an opaque error instead of an SDK hint. Fix: before theExprbranch at line 491, rejectOrderedColumnvalues with a CompileError whose hint isorder_by=.OrderedColumnis already imported. This applies to the shared_plan, which coversquery,debugandwhy.🔧 Fix applied.
2 issues (1 warning, 1 info) still open:
packages/inputlayer-py/src/inputlayer/knowledge_graph.py:491- The intent nameskg.why(View, order=...)as one of the failing calls. The new check only catches plain values.OrderedColumnsubclassesExpr, sokg.why(Reachable, order=Reachable.dst.desc())(and the same call throughquery/debug) still passes theisinstance(v, Expr)branch and becomes a computed column namedorder. The compiler'sbind()then emitsOrder = Dst:desc(compile_expr turns an OrderedColumn intovar:desc). That is invalid IQL, so the call fails at the engine with an opaque error instead of an SDK hint. Fix: before theExprbranch at line 491, rejectOrderedColumnvalues with a CompileError whose hint isorder_by=.OrderedColumnis already imported. This applies to the shared_plan, which coversquery,debugandwhy.packages/inputlayer-py/src/inputlayer/knowledge_graph.py:501- The plain-value branch always suggestswhere=lambda r: r.{k} == {v!r}, even whenkis not a column of any selected or joined relation. Example:kg.why(Reachable, order="desc")raises a CompileError (correct: nothing is sent), but its hintwhere=lambda r: r.order == 'desc'points at a column that doesn't exist. This is the same sort-keyword misuse that round 1's OrderedColumn branch (line 491) handles, so the string spelling was left behind. Optional fix: suggest where= only whenknames a column of a relation in the plan. Otherwise give a generic hint that mentions where=/order_by=.🔧 Fix applied.
3 issues (1 warning, 2 infos) still open:
packages/inputlayer-py/src/inputlayer/knowledge_graph.py:491- The intent nameskg.why(View, order=...)as one of the failing calls. The new check only catches plain values.OrderedColumnsubclassesExpr, sokg.why(Reachable, order=Reachable.dst.desc())(and the same call throughquery/debug) still passes theisinstance(v, Expr)branch and becomes a computed column namedorder. The compiler'sbind()then emitsOrder = Dst:desc(compile_expr turns an OrderedColumn intovar:desc). That is invalid IQL, so the call fails at the engine with an opaque error instead of an SDK hint. Fix: before theExprbranch at line 491, rejectOrderedColumnvalues with a CompileError whose hint isorder_by=.OrderedColumnis already imported. This applies to the shared_plan, which coversquery,debugandwhy.packages/inputlayer-py/src/inputlayer/knowledge_graph.py:501- The plain-value branch always suggestswhere=lambda r: r.{k} == {v!r}, even whenkis not a column of any selected or joined relation. Example:kg.why(Reachable, order="desc")raises a CompileError (correct: nothing is sent), but its hintwhere=lambda r: r.order == 'desc'points at a column that doesn't exist. This is the same sort-keyword misuse that round 1's OrderedColumn branch (line 491) handles, so the string spelling was left behind. Optional fix: suggest where= only whenknames a column of a relation in the plan. Otherwise give a generic hint that mentions where=/order_by=.packages/inputlayer-py/src/inputlayer/knowledge_graph.py:508- The where= hint added in the round-2 fix always suggests a one-argument lambda (where=lambda r: r.{k} == {v!r})._plancallswhere(*proxies)with one proxy per relation. So with more than one relation in play, for examplekg.query(Employee, Dept, join=[Employee, Dept], department='eng'), following the hint literally raises a TypeError. A related ordering issue:is_columnonly sees relations added so far. A value keyword placed before an aggregate keyword that brings in its relation, as inquery(department='eng', total=count(Employee.id)), gets the generic hint instead of the where= one. Both only affect hint wording. No invalid IQL is ever sent. Optional fix: emit the lambda form only whenlen(relations) == 1.🔧 **Test** - 2 issues found → no changes applied ✅
make python-sdk-live, or the evidence driver script against a local server, to complete live validation.uv run --extra dev pytest tests/test_compile_rules.py -k KeywordArguments -q(9 passed; transport is mocked, so this is not a live run)CARGO_TARGET_DIR=/tmp/nm-01M43-target cargo build --release --bin inputlayer-server(still compiling when this result was due)Wrote the live driver ~/.no-mistakes/evidence/01M43JZYRYY4ZZR5395W6HHBD9/drive_why.py and extracted the base-commit SDK to /tmp/nm-01M43-base for a before/after comparison (not executed: no server yet)🔧 No changes applied.
✅ Re-checked - no issues remain.
CARGO_INCREMENTAL=0 CARGO_PROFILE_RELEASE_DEBUG=0 cargo build --release --bin inputlayer-server(completed)INPUTLAYER_ADMIN_PASSWORD=admin target/release/inputlayer-server --host 127.0.0.1 --port 18392 --data-dir <tmp>PYTHONPATH=src python drive_why_scenarios.py head(live, head SDK)PYTHONPATH=<base sdk> python drive_why_scenarios.py base(live, base-commit SDK, before/after)pytest tests/docs_queries_live.py tests/compile_rules_live.py tests/subscriptions_live.pyagainst the live server (62 passed)pytest tests/test_compile_rules.py -k KeywordArguments(mocked)cargo clean✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.