refactor(search): make PUBLIC_FIELDS a tuple[FieldSpec, ...], drop PublicField

PublicField duplicated seven fields whoosh-compat's own FieldSpec already
has (name/kind/aliases/comma_values/date_only/fast/subpaths), and
_registry.py hand-copied all of them across on every registry build.
FieldSpec is a frozen dataclass with analyzer/pattern_normalizer already
optional (default None), so PUBLIC_FIELDS can just BE the FieldSpec tuple -
_schema.py only ever read name/kind/fast off it and needs no changes.
_registry.py now attaches the per-language analyzer/pattern_normalizer via
dataclasses.replace() instead of reconstructing every field from scratch.

FieldSpec.__post_init__ normalizes subpaths into a MappingProxyType, so
test_fields.py's exact-tuple-equality subpath assertions become set
comparisons; a genuinely empty subpaths is now `not field.subpaths` rather
than `== ()`.

Verified test_api_trash.py::test_api_trash's "Schema error: An index exists
but the schema does not match" failure is a pre-existing, unrelated local
environment issue (a stale, untracked data/index/ directory in this
checkout) - reproduces identically with this commit's changes stashed out.
This commit is contained in:
Trenton Holmes
2026-08-19 13:36:53 -07:00
committed by stumpylog
parent 45e6b1dcc6
commit 8cf4b0c997
4 changed files with 44 additions and 64 deletions
+3 -3
View File
@@ -20,7 +20,7 @@ class TestPublicFields:
def test_non_json_fields_have_no_subpaths(self) -> None:
for field in PUBLIC_FIELDS:
if field.kind is not FieldKind.JSON:
assert field.subpaths == ()
assert not field.subpaths
def test_document_type_alias_is_type(self) -> None:
field = next(f for f in PUBLIC_FIELDS if f.name == "document_type")
@@ -36,11 +36,11 @@ class TestPublicFields:
def test_notes_subpaths(self) -> None:
field = next(f for f in PUBLIC_FIELDS if f.name == "notes")
assert field.subpaths == ("user", "note")
assert set(field.subpaths) == {"user", "note"}
def test_custom_fields_subpaths(self) -> None:
field = next(f for f in PUBLIC_FIELDS if f.name == "custom_fields")
assert field.subpaths == ("name", "value")
assert set(field.subpaths) == {"name", "value"}
def test_no_internal_id_fields_present(self) -> None:
# tag_id/owner_id/viewer_id/etc. are permission-filter-only fields,
+2 -2
View File
@@ -130,7 +130,7 @@ class TestSchemaMatchesPublicFields:
class TestFastFlagAgreement:
def test_every_public_field_fast_flag_matches_the_built_schema(self) -> None:
# whoosh-compat's registry trusts PublicField.fast when resolving
# whoosh-compat's registry trusts PUBLIC_FIELDS' fast flag when resolving
# field:* existence checks (its FAST_FIELD strategy); a fast=True
# entry whose actual tantivy column is not fast would make those
# searches silently match nothing at search time. build_schema()
@@ -144,6 +144,6 @@ class TestFastFlagAgreement:
}
for public_field in PUBLIC_FIELDS:
assert schema_fast[public_field.name] == public_field.fast, (
f"{public_field.name}: PublicField.fast={public_field.fast} but the"
f"{public_field.name}: PUBLIC_FIELDS says fast={public_field.fast} but the"
f" built schema says fast={schema_fast[public_field.name]}"
)