Skip to content

feat(web): include_synsets option on forms-for-synsets batch [SIGN-640] - #6

Merged
AmitMY merged 1 commit into
mainfrom
sign-640-forms-include-synsets
Jul 20, 2026
Merged

feat(web): include_synsets option on forms-for-synsets batch [SIGN-640]#6
AmitMY merged 1 commit into
mainfrom
sign-640-forms-include-synsets

Conversation

@AmitMY

@AmitMY AmitMY commented Jul 20, 2026

Copy link
Copy Markdown

PR 2 of 3 for SIGN-640: the dictionary sitemap should emit <lastmod>.

What

POST /lexicons/{lexicon}/forms gains an optional body flag:

{ "synsets": ["test-en-0001-n", "test-en-0006-n"], "include_synsets": true }
→ { "data": { "information": ["test-en-0001-n"], "datum": ["test-en-0006-n"], "data": ["test-en-0006-n"] }, "meta": { "total": 3 } }

A word page's lastmod is the max over its signed synsets' change timestamps (which come from dictionary-api, sign/dictionary-api#73) — so the batch must say which synsets matched each form. Without the flag the response is the flat sorted form list, unchanged for existing callers.

Internally the query now selects (form, synset_id) pairs and both response shapes derive from one mapping — no second query path.

Tests

16 web tests pass (new: the map shape, including a secondary written form inheriting its entry's synsets). ruff, mypy, build, full suite (157) green.

🤖 Generated with Claude Code


Note

Low Risk
Backward-compatible optional response shape on a batch read endpoint; default behavior unchanged for existing clients.

Overview
Adds optional include_synsets on POST /lexicons/{lexicon}/forms so batch callers can see which synset IDs each matched form expresses—needed to compute per-word lastmod from synset change timestamps (SIGN-640).

_get_forms_for_synsets now returns a form → [synset_id, …] map built from a single query that selects (form, synset_id) pairs instead of distinct forms only. The handler still returns the flat sorted form list when include_synsets is omitted or false; with include_synsets: true, data is that map and meta.total stays the form count.

A web test covers the map shape, including a secondary written form (data) tied to the same synset as its entry.

Reviewed by Cursor Bugbot for commit c588e7c. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added an option to include synset IDs when retrieving forms associated with synsets.
    • Responses now provide each form alongside the synset IDs it expresses when enabled.
    • Form totals accurately reflect the number of returned forms.
  • Bug Fixes

    • Improved handling of invalid lexicon specifications during form lookups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The synset form lookup now associates each form with matching synset IDs. The forms endpoint accepts include_synsets, returning either this mapping or the existing sorted form list, with updated total metadata and test coverage.

Changes

Synset form mapping

Layer / File(s) Summary
Build form-to-synset mappings
wn/web.py
_get_forms_for_synsets queries form and synset IDs together, groups IDs by form, and returns an empty mapping for invalid lexicon specifications.
Expose optional synset mappings
wn/web.py, tests/web_test.py
forms_for_synsets handles include_synsets, selects the mapping or sorted form-list response shape, updates meta.total, and verifies the mapping response.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • sign/wn#5: Updates the same forms-for-synsets endpoint and helper to support form-to-synset-ID mappings.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding an include_synsets option to the forms-for-synsets batch endpoint.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sign-640-forms-include-synsets

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
wn/web.py (1)

419-423: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Guarantee deterministic ordering of the API response.

Because dictionaries preserve insertion order, the sequence in which rows are yielded by SQLite dictates the order of keys in the response when include_synsets=True. Additionally, if a single form expresses multiple synsets, the order of synset_ids in its corresponding list will also depend on the query's return order.

Consider appending an ORDER BY f.form, ss.id clause to the SQL query to guarantee a deterministic API response, which helps prevent flaky tests and unpredictable client-side behavior.

♻️ Proposed refactor

Apply this change immediately above the mapping block:

     if not with_entities:
         query += ' AND f.form = LOWER(f.form)'
+
+    query += ' ORDER BY f.form, ss.id'
 
     mapping: dict[str, list[str]] = {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wn/web.py` around lines 419 - 423, Update the SQL query used immediately
before the mapping construction to order rows by form and synset ID using ORDER
BY f.form, ss.id. Keep the existing mapping logic unchanged so both dictionary
key order and each form’s synset_id list are deterministic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@wn/web.py`:
- Around line 419-423: Update the SQL query used immediately before the mapping
construction to order rows by form and synset ID using ORDER BY f.form, ss.id.
Keep the existing mapping logic unchanged so both dictionary key order and each
form’s synset_id list are deterministic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a5d1ce94-f960-4b29-b785-0eab16d72f9d

📥 Commits

Reviewing files that changed from the base of the PR and between 5bd1efc and c588e7c.

📒 Files selected for processing (2)
  • tests/web_test.py
  • wn/web.py

@AmitMY
AmitMY merged commit ae6998d into main Jul 20, 2026
13 checks passed
@AmitMY
AmitMY deleted the sign-640-forms-include-synsets branch July 20, 2026 06:45
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