Sort path so Next is truely the alphabetical path next.
This commit is contained in:
parent
b969902ac5
commit
e6a833f6f5
24
main.py
24
main.py
@ -19,8 +19,9 @@ from fastapi.responses import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
file_mapping = {}
|
file_mapping: dict[str, str] = {}
|
||||||
indexers = []
|
indexers = []
|
||||||
|
sorted_hashes: list[str] = []
|
||||||
|
|
||||||
|
|
||||||
class FileIndexer:
|
class FileIndexer:
|
||||||
@ -164,7 +165,7 @@ INDEXER_MAP = {".zip": ZipFileIndexer}
|
|||||||
|
|
||||||
def initialize_server(args: argparse.Namespace):
|
def initialize_server(args: argparse.Namespace):
|
||||||
"""Initialize the server with directory or glob indexing"""
|
"""Initialize the server with directory or glob indexing"""
|
||||||
global file_mapping, indexers
|
global file_mapping, indexers, sorted_hashes
|
||||||
|
|
||||||
src_path = Path(args.source)
|
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)")
|
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")
|
@app.get("/api/health")
|
||||||
async def health_check():
|
async def health_check():
|
||||||
@ -283,7 +294,7 @@ def _get_navigation_data(file_hash: str, order: str | None = None):
|
|||||||
Returns:
|
Returns:
|
||||||
Dictionary with navigation hashes and filename.
|
Dictionary with navigation hashes and filename.
|
||||||
"""
|
"""
|
||||||
keys = list(file_mapping.keys())
|
keys = _get_sorted_hashes()
|
||||||
idx = keys.index(file_hash)
|
idx = keys.index(file_hash)
|
||||||
|
|
||||||
if order == "random":
|
if order == "random":
|
||||||
@ -523,6 +534,11 @@ def _get_random_hash() -> str:
|
|||||||
return random.choice(keys)
|
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:
|
def _get_random_navigate_path() -> str | None:
|
||||||
"""Get a random internal path from ZipFileIndexers only."""
|
"""Get a random internal path from ZipFileIndexers only."""
|
||||||
zip_paths: list[str] = []
|
zip_paths: list[str] = []
|
||||||
@ -593,7 +609,7 @@ def _get_navigation_data_by_path(
|
|||||||
if file_hash is None:
|
if file_hash is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
keys = list(file_mapping.keys())
|
keys = _get_sorted_hashes()
|
||||||
idx = keys.index(file_hash)
|
idx = keys.index(file_hash)
|
||||||
|
|
||||||
if order == "random":
|
if order == "random":
|
||||||
|
|||||||
@ -16,6 +16,7 @@ def _reset_state() -> None:
|
|||||||
"""Reset all global state to defaults."""
|
"""Reset all global state to defaults."""
|
||||||
main.file_mapping.clear()
|
main.file_mapping.clear()
|
||||||
main.indexers.clear()
|
main.indexers.clear()
|
||||||
|
main.sorted_hashes.clear()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
|||||||
@ -39,8 +39,8 @@ class TestGetNavigationData:
|
|||||||
assert data["file_hash"] == file_hash
|
assert data["file_hash"] == file_hash
|
||||||
|
|
||||||
def test_sequential_next_and_prev(self, seeded_indexers: None) -> None:
|
def test_sequential_next_and_prev(self, seeded_indexers: None) -> None:
|
||||||
"""In sequential mode, next and prev are adjacent in the list."""
|
"""In sequential mode, next and prev are adjacent in filename order."""
|
||||||
keys = list(main.file_mapping.keys())
|
keys = main._get_sorted_hashes()
|
||||||
if len(keys) < 2:
|
if len(keys) < 2:
|
||||||
pytest.skip("Need at least 2 files for sequential navigation")
|
pytest.skip("Need at least 2 files for sequential navigation")
|
||||||
file_hash = keys[0]
|
file_hash = keys[0]
|
||||||
@ -51,7 +51,7 @@ class TestGetNavigationData:
|
|||||||
|
|
||||||
def test_middle_item_navigation(self, seeded_indexers: None) -> None:
|
def test_middle_item_navigation(self, seeded_indexers: None) -> None:
|
||||||
"""Middle item has correct prev and next."""
|
"""Middle item has correct prev and next."""
|
||||||
keys = list(main.file_mapping.keys())
|
keys = main._get_sorted_hashes()
|
||||||
if len(keys) < 3:
|
if len(keys) < 3:
|
||||||
pytest.skip("Need at least 3 files for middle-item test")
|
pytest.skip("Need at least 3 files for middle-item test")
|
||||||
mid_idx = len(keys) // 2
|
mid_idx = len(keys) // 2
|
||||||
@ -62,7 +62,7 @@ class TestGetNavigationData:
|
|||||||
|
|
||||||
def test_last_item_wraps_next(self, seeded_indexers: None) -> None:
|
def test_last_item_wraps_next(self, seeded_indexers: None) -> None:
|
||||||
"""Last item's next wraps to the first item."""
|
"""Last item's next wraps to the first item."""
|
||||||
keys = list(main.file_mapping.keys())
|
keys = main._get_sorted_hashes()
|
||||||
if len(keys) < 2:
|
if len(keys) < 2:
|
||||||
pytest.skip("Need at least 2 files for wrap test")
|
pytest.skip("Need at least 2 files for wrap test")
|
||||||
file_hash = keys[-1]
|
file_hash = keys[-1]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user