Skip to content

Commit

Permalink
Fix ordering inside searchindex.js not being deterministic
Browse files Browse the repository at this point in the history
  • Loading branch information
pietroalbini committed Sep 1, 2023
1 parent fcc3899 commit fa9e7c0
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
20 changes: 20 additions & 0 deletions CHANGES
@@ -1,3 +1,23 @@
Release 7.2.6 (in development)
==============================

Dependencies
------------

Incompatible changes
--------------------

Deprecated
----------

Features added
--------------

Bugs fixed
----------

* #11622: Fix ordering inside searchindex.js not being deterministic.

Release 7.2.5 (released Aug 30, 2023)
=====================================

Expand Down
2 changes: 1 addition & 1 deletion sphinx/search/__init__.py
Expand Up @@ -162,7 +162,7 @@ class _JavaScriptIndex:
SUFFIX = ')'

def dumps(self, data: Any) -> str:
return self.PREFIX + json.dumps(data) + self.SUFFIX
return self.PREFIX + json.dumps(data, sort_keys=True) + self.SUFFIX

def loads(self, s: str) -> Any:
data = s[len(self.PREFIX):-len(self.SUFFIX)]
Expand Down
23 changes: 23 additions & 0 deletions tests/test_search.py
Expand Up @@ -304,3 +304,26 @@ def test_parallel(app):
app.build()
index = load_searchindex(app.outdir / 'searchindex.js')
assert index['docnames'] == ['index', 'nosearch', 'tocitem']


@pytest.mark.sphinx(testroot='search')
def test_search_index_is_deterministic(app):
app.builder.build_all()
index = load_searchindex(app.outdir / 'searchindex.js')

def check_if_dicts_are_sorted(item):
if type(item) == dict:
keys = list(item.keys())
if not all(keys[i] <= keys[i + 1] for i in range(len(keys) - 1)):
raise RuntimeError(f'keys are not sorted: {item!r}')

for child in item.values():
check_if_dicts_are_sorted(child)
# Lists in the search index cannot be sorted: for some lists, their
# position inside the list is referenced elsewhere in the index, so if
# we were to sort lists, the search index would break.
elif type(item) == list:
for child in item:
check_if_dicts_are_sorted(child)

check_if_dicts_are_sorted(index)

0 comments on commit fa9e7c0

Please sign in to comment.