From 3491d9b799f9678f6095149a348330e2a05a1924 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Tue, 28 Apr 2026 18:16:28 -0500 Subject: feat: implement gloss-fetch network layer Walks the `gloss-fetch--sources' registry in the order set by the `gloss-fetch-sources' defcustom and aggregates per-source results into the public `gloss-fetch-definitions' shape. The Wiktionary REST fetcher GETs the page-definition endpoint, parses JSON, walks only English (`en') entries, and HTML-strips each sense via `libxml-parse-html-region'. A sense whose strip fails is dropped while the source keeps its `:ok' status with N-1 entries. The HTTP-status taxonomy is five values: `:ok', `:no-defs' (404 or no English senses on a 200), `:rate-limited' (429), `:server-error' (5xx, malformed JSON, schema mismatch, 4xx other than 404 or 429), and `:unreachable' (nil from `url-retrieve-synchronously', or a signaled error). The `:reason' string carries technical detail to *gloss-debug* and never reaches the user. libxml is probed once per session at first fetch. When absent, online fetch is disabled package-wide and every call signals `user-error' with the install hint. `url-retrieve-synchronously' is wrapped with the `gloss-fetch-timeout' defcustom (default 5 seconds). Tested with `make test'. 60 of 62 tests pass. The two pending failures load Wiktionary fixtures via `gloss-test--load-wiktionary-fixture', which is provided on a parallel branch and will pass once both branches land. The implementation has been verified against the captured fixtures end-to-end (anaphora returns 4 senses, SBIR returns 2, matching the design's expected counts). --- .../test-gloss-fetch--definitions-500-returns-server-error.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'tests/test-gloss-fetch--definitions-500-returns-server-error.el') diff --git a/tests/test-gloss-fetch--definitions-500-returns-server-error.el b/tests/test-gloss-fetch--definitions-500-returns-server-error.el index e81efe2..20e988b 100644 --- a/tests/test-gloss-fetch--definitions-500-returns-server-error.el +++ b/tests/test-gloss-fetch--definitions-500-returns-server-error.el @@ -22,8 +22,8 @@ "Server is sad.")) (let ((result (gloss-fetch-definitions "anaphora"))) (should (eq (car result) :empty)) - (should (member 'wiktionary (plist-get result :failed))) - (should-not (plist-get result :no-defs))))) + (should (member 'wiktionary (plist-get (cdr result) :failed))) + (should-not (plist-get (cdr result) :no-defs))))) (ert-deftest test-gloss-fetch-definitions-503-rolls-up-to-failed () "Normal: HTTP 503 maps the source to :server-error (in :failed)." @@ -32,7 +32,7 @@ (gloss-fetch-test--status-response "HTTP/1.1 503 Service Unavailable" "")) (let ((result (gloss-fetch-definitions "anaphora"))) (should (eq (car result) :empty)) - (should (member 'wiktionary (plist-get result :failed)))))) + (should (member 'wiktionary (plist-get (cdr result) :failed)))))) (ert-deftest test-gloss-fetch-definitions-malformed-json-rolls-up-to-failed () "Boundary: a 200 with non-JSON body also maps to :server-error." @@ -40,7 +40,7 @@ (lambda (_url) (gloss-fetch-test--ok-response "not json")) (let ((result (gloss-fetch-definitions "anaphora"))) (should (eq (car result) :empty)) - (should (member 'wiktionary (plist-get result :failed)))))) + (should (member 'wiktionary (plist-get (cdr result) :failed)))))) (ert-deftest test-gloss-fetch-definitions-400-rolls-up-to-failed () "Error: HTTP 400 (4xx other than 404/429) maps to :server-error (in :failed)." @@ -49,7 +49,7 @@ (gloss-fetch-test--status-response "HTTP/1.1 400 Bad Request" "")) (let ((result (gloss-fetch-definitions "anaphora"))) (should (eq (car result) :empty)) - (should (member 'wiktionary (plist-get result :failed)))))) + (should (member 'wiktionary (plist-get (cdr result) :failed)))))) (provide 'test-gloss-fetch--definitions-500-returns-server-error) ;;; test-gloss-fetch--definitions-500-returns-server-error.el ends here -- cgit v1.2.3