Skip to content

feat(web): POST forms-for-synsets batch endpoint [SIGN-690] - #5

Merged
AmitMY merged 3 commits into
mainfrom
sign-690-forms-synsets
Jul 17, 2026
Merged

feat(web): POST forms-for-synsets batch endpoint [SIGN-690]#5
AmitMY merged 3 commits into
mainfrom
sign-690-forms-synsets

Conversation

@AmitMY

@AmitMY AmitMY commented Jul 16, 2026

Copy link
Copy Markdown

Part of SIGN-690: the dictionary website should only surface (sitemap, A-Z browse) concepts that have signs. The dictionary API knows which synsets have signs; this endpoint answers "which forms express any of these synsets" — with the join running in wn's SQLite instead of shipping the whole form→synsets map to the caller.

What

POST /lexicons/{lexicon}/forms with {"synsets": ["omw-en-02084071-n", ...]} → the unique forms having at least one sense in those synsets:

{ "data": ["dog", ...], "meta": { "total": 1 } }
  • Same base query as the GET forms list, joined through senses to synsets; with_entities composes (body field).
  • The id list binds as a single json_each parameter, so it clears SQLite's variable-count limit at any batch size.
  • GET /lexicons/{lexicon}/forms is unchanged; POST follows the existing POST /lexicons/{lexicon}/definitions batch precedent.
  • Non-string ids → 400; unknown ids are simply unmatched.

Tests

Plain GET forms (previously untested), the POST batch (including a secondary written form inheriting its entry's synsets), empty/unknown ids, non-string rejection, bad lexicon specifier. Local CI: ruff, mypy, build, full pytest suite (155) all pass.

🤖 Generated with Claude Code


Note

Low Risk
Additive read-only API and SQL; no auth or data mutation. Risk is mainly query correctness and input validation, which the new tests exercise.

Overview
Adds POST /lexicons/{lexicon}/forms so callers can batch-resolve distinct written forms that express any of a given synset id list—intended for dictionary sitemap/A-Z surfaces that only show concepts with signs, without shipping a full form→synset map.

The handler mirrors the existing POST …/definitions pattern: JSON body {"synsets": [...], "with_entities": ...}, response {"data": [...], "meta": {"total": N}}, with 400 on invalid JSON or non-string synset ids. GET …/forms is unchanged.

Implementation adds _get_forms_for_synsets, extending the GET forms SQL with joins through senses and synsets, filtering ids via json_each(?) so large batches stay within SQLite’s bound-parameter limits. Malformed lexicon specifiers yield an empty list (same as GET forms).

Tests cover GET forms listing, POST batch results (including secondary written forms), empty/unknown ids, validation errors, and bad lexicon specifiers.

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

Summary by CodeRabbit

  • New Features
    • Added a POST capability for /lexicons/{lexicon}/forms to return distinct written forms filtered by a provided synsets list.
    • Supports with_entities to control how returned forms are normalized.
    • Responses include meta.total, including 0 with an empty result when the lexicon specifier is malformed.
  • Tests
    • Added pytest coverage for GET listing and POST synset-driven results, including empty/unknown IDs and validation for non-string IDs.

…GN-690]

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

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The forms endpoint now supports POST requests that return written forms for supplied synset IDs. The implementation validates request data, queries distinct forms, supports entity filtering, and reports totals. Tests cover normal, empty, invalid, and malformed-input cases.

Changes

Forms filtered by synsets

Layer / File(s) Summary
Synset-filtered forms endpoint
wn/web.py
Adds a cached SQL lookup, validates POST request fields, supports with_entities, and returns filtered forms with meta.total.
Endpoint response coverage
tests/web_test.py
Tests plain listings, synset-filtered forms, secondary forms, empty and unknown IDs, invalid ID types, totals, and malformed lexicon specifiers.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant forms_for_synsets
  participant _get_forms_for_synsets
  participant SQLDatabase
  Client->>forms_for_synsets: POST synset IDs and with_entities
  forms_for_synsets->>_get_forms_for_synsets: Validate and query forms
  _get_forms_for_synsets->>SQLDatabase: Join forms, senses, and synsets
  SQLDatabase-->>_get_forms_for_synsets: Distinct written forms
  _get_forms_for_synsets-->>forms_for_synsets: Form list
  forms_for_synsets-->>Client: JSON data and meta.total
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change: adding a POST forms-for-synsets batch endpoint.
✨ 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-690-forms-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.

…ue map [SIGN-690]

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AmitMY
AmitMY force-pushed the sign-690-forms-synsets branch from 5b7c82e to 543d750 Compare July 17, 2026 09:03
@AmitMY AmitMY changed the title feat(web): add synsets=true variant to the lexicon forms endpoint [SIGN-690] feat(web): POST forms-for-synsets batch endpoint [SIGN-690] Jul 17, 2026

@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.

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@tests/web_test.py`:
- Line 161: Add the pytest.mark.usefixtures('mini_db_web') decorator to
test_forms_for_synsets, matching the surrounding tests and ensuring it runs with
the mini_db_web fixture.

In `@wn/web.py`:
- Around line 449-450: Validate the request payload around `await
request.json()` before accessing `body.get`: catch malformed JSON errors and
return a 400 Bad Request, then verify the parsed `body` is a dictionary and
return 400 for other JSON types. Preserve the existing `synset_ids` extraction
for valid object payloads.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5a3af29e-6989-4d17-927a-13fff3a8e469

📥 Commits

Reviewing files that changed from the base of the PR and between fb18ff0 and 543d750.

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

Comment thread tests/web_test.py
Comment thread wn/web.py Outdated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AmitMY
AmitMY merged commit f74e129 into main Jul 17, 2026
13 checks passed
@AmitMY
AmitMY deleted the sign-690-forms-synsets branch July 17, 2026 09:24
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