Skip to content

fix: freeze unhashable args in Query.test to prevent TypeError#618

Open
gaoflow wants to merge 1 commit into
msiemens:masterfrom
gaoflow:fix/query-test-unhashable-args
Open

fix: freeze unhashable args in Query.test to prevent TypeError#618
gaoflow wants to merge 1 commit into
msiemens:masterfrom
gaoflow:fix/query-test-unhashable-args

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 24, 2026

Copy link
Copy Markdown

Problem

Passing a list or dict as an extra argument to Query().field.test() raises
TypeError: unhashable type: 'list' (or 'dict') the first time TinyDB tries
to hash the resulting QueryInstance for the query cache.

def in_set(val, allowed):
    return val in allowed

db.search(Query().x.test(in_set, [1, 2, 3]))  # TypeError: unhashable type: 'list'

Reported in #514 (issue #517).

Root cause

Query.test builds its cache key tuple as:

('test', self._path, func, args)

args is a raw Python tuple that can contain unhashable objects (list,
dict). Every other query method that accepts caller-supplied values
(any, all, one_of, fragment) already passes them through the
existing freeze() helper before building the hash tuple. test was
the only method that did not.

Fix

Apply freeze() to each element of args before composing the hash
tuple, matching the pattern used by the sibling methods:

('test', self._path, func, tuple(freeze(arg) for arg in args))

freeze() recursively converts listtuple, dictFrozenDict,
and setfrozenset, so nested unhashable structures are handled too.
The test function still receives the original (unfrozen) args at
call-time; only the hash key is affected.

Tests

Added test_custom_with_unhashable_params in tests/test_queries.py
covering list args, dict args, same-args hash stability, and different-args
hash distinctness.

Passing list or dict values as extra arguments to Query().field.test()
raised TypeError: unhashable type when the resulting QueryInstance was
hashed (e.g. on first use with a caching Table).  The other query
methods (any, all, one_of, fragment) already call freeze() on their
arguments; apply the same treatment to each element of the *args tuple
in Query.test().

Fixes msiemens#517
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.

1 participant