Skip to content

fix(query): _handle_keyword coerces non-iterable values to single-element list (#152)#153

Merged
jensens merged 1 commit into
mainfrom
fix/handle-keyword-non-iterable-value
Apr 20, 2026
Merged

fix(query): _handle_keyword coerces non-iterable values to single-element list (#152)#153
jensens merged 1 commit into
mainfrom
fix/handle-keyword-non-iterable-value

Conversation

@jensens
Copy link
Copy Markdown
Member

@jensens jensens commented Apr 20, 2026

Summary

Closes #152. Another ZCatalog-compat rough edge exposed after the b61 deploy freed up the code path.

Bug

```python

_handle_keyword

query_val = [query_val] if isinstance(query_val, str) else list(query_val)
```

This assumes the value is either a `str` or iterable. A Zope `DateTime`, Python `datetime`, plain `int`, or any other non-iterable scalar hits `list(value)` and raises `TypeError: 'DateTime' object is not iterable`.

Observed on aaf-6 prod via `plone.app.querystring.querybuilder.html_results` (Collection edit widget live-preview) where a caller routed a `DateTime` through a keyword-index criterion by mistake.

Fix

Treat only true iterables (`list`, `tuple`, `set`, `frozenset`) as collections; anything else — string, scalar, or object with `str` but no `iter` — is a single-value scalar. All values are coerced to `str()` to match the JSONB storage shape (keyword arrays always contain strings).

Why not block upstream instead

The upstream root cause is a buggy caller passing the wrong type. But the pgcatalog `TypeError` is too brittle — it surfaces as a 500 error for end users. The robust fix is to coerce silently; the upstream bug can be chased separately but should not take down renders.

Test plan

  • Two new regression tests in `TestKeywordIndex`: `_NotIterable` stand-in for Zope DateTime, Python datetime directly.
  • Existing keyword tests (single str, list or/and, default operator) unaffected.
  • Full suite: 1444 passed / 23 skipped / 0 failed.
  • After deploy: `@@querybuilder_html_results` on affected Collection no longer 500s.

🤖 Generated with Claude Code

…ment list (#152)

Previous: 'query_val = [query_val] if isinstance(query_val, str) else list(query_val)' assumed value is str or iterable. A Zope DateTime / Python datetime / int hit list(value) and raised TypeError: object is not iterable.

Now: treat list/tuple/set/frozenset as iterable-of-keywords, everything else as single-value scalar. Coerce with str() to match JSONB storage shape.

Closes #152.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jensens jensens merged commit 800adfc into main Apr 20, 2026
5 checks passed
@jensens jensens deleted the fix/handle-keyword-non-iterable-value branch April 20, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

_handle_keyword crashes on non-iterable, non-str query values (DateTime, int, ...)

1 participant