Skip to content

Commit 7943d49

Browse files
committed
fix(wtsite): reject a modify_search_results query without titles
- return_json and return_meta yield dicts and objects, not page titles - raise ValueError instead of failing later inside GetPageParam - covers both search modes, since prefix_search honours return_json too
1 parent 91c3d7e commit 7943d49

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

‎src/osw/wtsite.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,12 @@ def modify_search_results(
693693
dryrun
694694
Deprecated, use param.dryrun instead. if True, no actual changes are
695695
made, by default False
696+
697+
Raises
698+
------
699+
ValueError
700+
If param.query is a SearchParam asking for anything other than page
701+
titles, meaning return_json or return_meta.
696702
"""
697703
if not isinstance(param, WtSite.ModifySearchResultsParam):
698704
param = WtSite.ModifySearchResultsParam(
@@ -703,6 +709,23 @@ def modify_search_results(
703709
dryrun=dryrun,
704710
)
705711

712+
# Both searches can be asked for the raw API response, and the semantic
713+
# one for SemanticSearchResult objects. This method looks up and edits
714+
# a page per result, so it needs the titles themselves. Reject the
715+
# other options here rather than failing further down on a dict where
716+
# a title is expected
717+
if isinstance(param.query, wt.SearchParam):
718+
unsupported = [
719+
name
720+
for name in ("return_json", "return_meta")
721+
if getattr(param.query, name)
722+
]
723+
if unsupported:
724+
raise ValueError(
725+
f"modify_search_results edits a page per search result, so "
726+
f"the query must not set {' or '.join(unsupported)}."
727+
)
728+
706729
titles = []
707730
if param.mode == "prefix":
708731
titles = wt.prefix_search(self._site, param.query)

‎tests/test_wtsite_modify_search_results.py‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
import threading
99

10+
import pytest
11+
12+
import osw.wiki_tools as wt
1013
import osw.wtsite as wtsite_mod
1114
from osw.wtsite import WtPage, WtSite
1215

@@ -144,3 +147,48 @@ def test_modify_search_results_legacy_keyword_call_still_works(monkeypatch):
144147

145148
assert handled == titles
146149
assert comments == [("Item:OSW1", "[bot] legacy")]
150+
151+
152+
@pytest.mark.parametrize("mode", ["prefix", "semantic"])
153+
@pytest.mark.parametrize("flag", ["return_json", "return_meta"])
154+
def test_modify_search_results_rejects_a_query_not_asking_for_titles(
155+
monkeypatch, mode, flag
156+
):
157+
"""A search asked for raw responses or result objects yields no titles to
158+
edit, so the method must say so instead of failing on the first result."""
159+
ws = _make_fake_wtsite()
160+
# Would hand back dicts rather than titles if the guard let the call through
161+
_stub_search(monkeypatch, [{"fulltext": "Item:OSW1"}])
162+
163+
param = WtSite.ModifySearchResultsParam(
164+
mode=mode,
165+
query=wt.SearchParam(query="[[Category:Item]]", **{flag: True}),
166+
comment="[bot] test",
167+
)
168+
169+
with pytest.raises(ValueError, match=flag):
170+
ws.modify_search_results(param, modify_page=lambda wtpage: None)
171+
172+
173+
@pytest.mark.parametrize("mode", ["prefix", "semantic"])
174+
def test_modify_search_results_accepts_a_plain_search_param(monkeypatch, mode):
175+
"""The guard must not reject a SearchParam that does ask for titles."""
176+
ws = _make_fake_wtsite()
177+
titles = ["Item:OSW1"]
178+
pages = _make_pages(ws, titles)
179+
comments = []
180+
181+
_stub_search(monkeypatch, titles)
182+
_stub_get_page(monkeypatch, ws, pages)
183+
_stub_edits(monkeypatch, pages, comments)
184+
185+
handled = []
186+
187+
param = WtSite.ModifySearchResultsParam(
188+
mode=mode,
189+
query=wt.SearchParam(query="[[Category:Item]]"),
190+
comment="[bot] test",
191+
)
192+
ws.modify_search_results(param, modify_page=lambda wtpage: handled.append(1))
193+
194+
assert handled == [1]

0 commit comments

Comments
 (0)