Sort path so Next is truely the alphabetical path next.

This commit is contained in:
Timothy Farrell 2026-05-07 17:07:09 +00:00
parent b969902ac5
commit e6a833f6f5
3 changed files with 25 additions and 8 deletions

24
main.py
View File

@ -19,8 +19,9 @@ from fastapi.responses import (
)
app = FastAPI()
file_mapping = {}
file_mapping: dict[str, str] = {}
indexers = []
sorted_hashes: list[str] = []
class FileIndexer:
@ -164,7 +165,7 @@ INDEXER_MAP = {".zip": ZipFileIndexer}
def initialize_server(args: argparse.Namespace):
"""Initialize the server with directory or glob indexing"""
global file_mapping, indexers
global file_mapping, indexers, sorted_hashes
src_path = Path(args.source)
@ -191,6 +192,16 @@ def initialize_server(args: argparse.Namespace):
print(f"Indexed {len(file_mapping)} files from {len(indexers)} source(s)")
# Build a sorted index for filename-ordered navigation
sorted_hashes = sorted(
file_mapping.keys(),
key=lambda h: (
(indexer.get_filename_by_hash(h) or "").lower()
if (indexer := _find_indexer_for_hash(h))
else ""
),
)
@app.get("/api/health")
async def health_check():
@ -283,7 +294,7 @@ def _get_navigation_data(file_hash: str, order: str | None = None):
Returns:
Dictionary with navigation hashes and filename.
"""
keys = list(file_mapping.keys())
keys = _get_sorted_hashes()
idx = keys.index(file_hash)
if order == "random":
@ -523,6 +534,11 @@ def _get_random_hash() -> str:
return random.choice(keys)
def _get_sorted_hashes() -> list[str]:
"""Return the cached filename-sorted hash list (built at index time)."""
return sorted_hashes
def _get_random_navigate_path() -> str | None:
"""Get a random internal path from ZipFileIndexers only."""
zip_paths: list[str] = []
@ -593,7 +609,7 @@ def _get_navigation_data_by_path(
if file_hash is None:
return None
keys = list(file_mapping.keys())
keys = _get_sorted_hashes()
idx = keys.index(file_hash)
if order == "random":

View File

@ -16,6 +16,7 @@ def _reset_state() -> None:
"""Reset all global state to defaults."""
main.file_mapping.clear()
main.indexers.clear()
main.sorted_hashes.clear()
@pytest.fixture(autouse=True)

View File

@ -39,8 +39,8 @@ class TestGetNavigationData:
assert data["file_hash"] == file_hash
def test_sequential_next_and_prev(self, seeded_indexers: None) -> None:
"""In sequential mode, next and prev are adjacent in the list."""
keys = list(main.file_mapping.keys())
"""In sequential mode, next and prev are adjacent in filename order."""
keys = main._get_sorted_hashes()
if len(keys) < 2:
pytest.skip("Need at least 2 files for sequential navigation")
file_hash = keys[0]
@ -51,7 +51,7 @@ class TestGetNavigationData:
def test_middle_item_navigation(self, seeded_indexers: None) -> None:
"""Middle item has correct prev and next."""
keys = list(main.file_mapping.keys())
keys = main._get_sorted_hashes()
if len(keys) < 3:
pytest.skip("Need at least 3 files for middle-item test")
mid_idx = len(keys) // 2
@ -62,7 +62,7 @@ class TestGetNavigationData:
def test_last_item_wraps_next(self, seeded_indexers: None) -> None:
"""Last item's next wraps to the first item."""
keys = list(main.file_mapping.keys())
keys = main._get_sorted_hashes()
if len(keys) < 2:
pytest.skip("Need at least 2 files for wrap test")
file_hash = keys[-1]