Skip to content

Commit 3f36d77

Browse files
committed
fix(wiki_tools): return list of full responses for prefix_search return_json
prefix_search with SearchParam.return_json=True returned result['query']['prefixsearch'] (the page-entry list) and still ran it through the flat-list comprehension, merging entries across queries into a single flat list and contradicting the docstring's promise of the full API response per query. Mirror the semantic_search behavior: the inner helper now returns the full raw prefixsearch API response, and the outer function skips the flatten when return_json=True, returning a list of response dicts (one per query, always a list even for a single query). The default return_json=False behavior (flat list of page titles) is unchanged. Add unit tests covering return_json=True for a single query and a list of queries, plus return_json=False still returning a flat list of titles.
1 parent 4daff1f commit 3f36d77

2 files changed

Lines changed: 74 additions & 13 deletions

File tree

‎src/osw/wiki_tools.py‎

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def __init__(self, **data):
150150

151151
def prefix_search(
152152
site: mwclient.client.Site, text: Union[str, SearchParam]
153-
) -> List[str]:
153+
) -> Union[List[str], List[dict]]:
154154
"""Standard query. Equivalent to the following mediawiki API call
155155
api.php?action=query&list=prefixsearch&pssearch=Star Wars.
156156
@@ -165,15 +165,17 @@ def prefix_search(
165165
166166
Returns
167167
-------
168-
page_list :
169-
List of page titles
168+
result:
169+
With ``return_json=False`` (default): a flat list of page titles. With
170+
``return_json=True``: a list of raw MediaWiki ``prefixsearch`` API response
171+
dicts, one per query (always a list, even for a single query).
170172
"""
171173
if not isinstance(text, SearchParam):
172174
query = SearchParam(query=text)
173175
else:
174176
query = text
175177

176-
def prefix_search_(single_text):
178+
def prefix_search_(single_text) -> Union[List[str], dict]:
177179
page_list = list()
178180
result = site.api(
179181
"query",
@@ -182,15 +184,16 @@ def prefix_search_(single_text):
182184
pslimit=query.limit,
183185
format="json",
184186
)
185-
if len(result["query"]["prefixsearch"]) == 0:
187+
if query.debug and len(result["query"]["prefixsearch"]) == 0:
188+
print("No results")
189+
if query.return_json:
190+
return result
191+
192+
for page in result["query"]["prefixsearch"]:
193+
title = page["title"]
186194
if query.debug:
187-
print("No results")
188-
else:
189-
for page in result["query"]["prefixsearch"]:
190-
title = page["title"]
191-
if query.debug:
192-
print(title)
193-
page_list.append(title)
195+
print(title)
196+
page_list.append(title)
194197
return page_list
195198

196199
if query.parallel:
@@ -200,11 +203,17 @@ def prefix_search_(single_text):
200203
else:
201204
query_results = [prefix_search_(single_text=sq) for sq in query.query]
202205

206+
if query.return_json:
207+
# Each entry of query_results is the raw API response dict for one query.
208+
# Do not flatten dicts; always return the list of responses (one per query),
209+
# even when only a single query was passed.
210+
return query_results
211+
203212
return [item for sublist in query_results for item in sublist]
204213
# todo: @Simon: a list of lists of strings (sublist for each query in query list)
205214
# or a list of strings (results of all queries combined)?
206215
# The last option would not change the behavior of the function, but would
207-
# return page_list # original return
216+
# return page_list # original return
208217

209218

210219
def semantic_search(

‎tests/test_wiki_tools.py‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,55 @@ def test_semantic_search_returns_flat_list_of_titles():
7676

7777
# return_json=False (the default) still yields a flat list of page titles
7878
assert out == ["Item:OSW1", "Item:OSW2"]
79+
80+
81+
def _prefixsearch_result(*titles):
82+
"""Build a minimal MediaWiki ``prefixsearch`` API result dict."""
83+
return {
84+
"batchcomplete": "",
85+
"query": {
86+
"prefixsearch": [
87+
{"ns": 0, "title": title, "pageid": idx}
88+
for idx, title in enumerate(titles, start=1)
89+
]
90+
},
91+
}
92+
93+
94+
def test_prefix_search_return_json_single_query_returns_list_with_full_response():
95+
result = _prefixsearch_result("Star Wars", "Star Trek")
96+
site = MagicMock()
97+
site.api.return_value = result
98+
99+
out = wt.prefix_search(site, wt.SearchParam(query="Star", return_json=True))
100+
101+
# A single query returns a list of one full API response dict, not a flattened
102+
# list of individual prefixsearch entries
103+
assert isinstance(out, list)
104+
assert out == [result]
105+
assert out[0]["query"]["prefixsearch"][0]["title"] == "Star Wars"
106+
107+
108+
def test_prefix_search_return_json_list_returns_list_of_full_responses():
109+
result_a = _prefixsearch_result("Star Wars")
110+
result_b = _prefixsearch_result("Voyager")
111+
site = MagicMock()
112+
site.api.side_effect = [result_a, result_b]
113+
114+
out = wt.prefix_search(
115+
site, wt.SearchParam(query=["Star", "Voy"], return_json=True)
116+
)
117+
118+
# One full API response dict per query, not merged/flattened across queries
119+
assert out == [result_a, result_b]
120+
121+
122+
def test_prefix_search_returns_flat_list_of_titles():
123+
result = _prefixsearch_result("Star Wars", "Star Trek")
124+
site = MagicMock()
125+
site.api.return_value = result
126+
127+
out = wt.prefix_search(site, "Star")
128+
129+
# return_json=False (the default) still yields a flat list of page titles
130+
assert out == ["Star Wars", "Star Trek"]

0 commit comments

Comments
 (0)