Add index backend
This commit is contained in:
parent
8ebb288d1c
commit
973d60008d
74
amanuensis/backend/index.py
Normal file
74
amanuensis/backend/index.py
Normal file
@ -0,0 +1,74 @@
|
||||
"""
|
||||
Index query interface
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
from amanuensis.db import DbContext, ArticleIndex, IndexType
|
||||
from amanuensis.errors import ArgumentError
|
||||
|
||||
|
||||
def create(
|
||||
db: DbContext,
|
||||
lexicon_id: int,
|
||||
index_type: IndexType,
|
||||
pattern: str,
|
||||
logical_order: int,
|
||||
display_order: int,
|
||||
capacity: Optional[int],
|
||||
) -> ArticleIndex:
|
||||
"""
|
||||
Create a new index in a lexicon.
|
||||
"""
|
||||
# Verify argument types are correct
|
||||
if not isinstance(lexicon_id, int):
|
||||
raise ArgumentError("lexicon_id")
|
||||
if not isinstance(index_type, IndexType):
|
||||
raise ArgumentError("index_type")
|
||||
if not isinstance(pattern, str):
|
||||
raise ArgumentError("pattern")
|
||||
if not isinstance(logical_order, int):
|
||||
raise ArgumentError("logical_order")
|
||||
if not isinstance(display_order, int):
|
||||
raise ArgumentError("display_order")
|
||||
if capacity is not None and not isinstance(capacity, int):
|
||||
raise ArgumentError("capacity")
|
||||
|
||||
# Verify the pattern is valid for the index type:
|
||||
if index_type == IndexType.CHAR:
|
||||
if len(pattern) < 1:
|
||||
raise ArgumentError(
|
||||
f"Pattern '{pattern}' too short for index type {index_type}"
|
||||
)
|
||||
elif index_type == IndexType.RANGE:
|
||||
range_def = re.match(r"^(.)-(.)$", pattern)
|
||||
if not range_def:
|
||||
raise ArgumentError(f"Pattern '{pattern}' is not a valid range format")
|
||||
start_char, end_char = range_def.group(1), range_def.group(2)
|
||||
if start_char >= end_char:
|
||||
raise ArgumentError(
|
||||
f"Range start '{start_char}' is not before range end '{end_char}'"
|
||||
)
|
||||
elif index_type == IndexType.PREFIX:
|
||||
if len(pattern) < 1:
|
||||
raise ArgumentError(
|
||||
f"Pattern '{pattern}' too short for index type {index_type}"
|
||||
)
|
||||
elif index_type == IndexType.ETC:
|
||||
if len(pattern) < 1:
|
||||
raise ArgumentError(
|
||||
f"Pattern '{pattern}' too short for index type {index_type}"
|
||||
)
|
||||
|
||||
new_index = ArticleIndex(
|
||||
lexicon_id=lexicon_id,
|
||||
index_type=index_type,
|
||||
pattern=pattern,
|
||||
logical_order=logical_order,
|
||||
display_order=display_order,
|
||||
capacity=capacity,
|
||||
)
|
||||
db.session.add(new_index)
|
||||
db.session.commit()
|
||||
return new_index
|
50
tests/test_index.py
Normal file
50
tests/test_index.py
Normal file
@ -0,0 +1,50 @@
|
||||
from amanuensis.db.models import IndexType
|
||||
import pytest
|
||||
|
||||
import amanuensis.backend.index as indq
|
||||
from amanuensis.db import DbContext, Lexicon, User
|
||||
|
||||
from amanuensis.errors import ArgumentError
|
||||
|
||||
|
||||
def test_create_index(db: DbContext, make):
|
||||
"""Test new index creation"""
|
||||
lexicon: Lexicon = make.lexicon()
|
||||
defaults: dict = {
|
||||
"db": db,
|
||||
"lexicon_id": lexicon.id,
|
||||
"index_type": IndexType.ETC,
|
||||
"pattern": "&c.",
|
||||
"logical_order": 0,
|
||||
"display_order": 0,
|
||||
"capacity": 0,
|
||||
}
|
||||
kwargs: dict
|
||||
|
||||
# Character indexes require nonempty patterns
|
||||
with pytest.raises(ArgumentError):
|
||||
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": ""}
|
||||
indq.create(**kwargs)
|
||||
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": "ABC"}
|
||||
assert indq.create(**kwargs)
|
||||
|
||||
# Range indexes must follow the 1-2 format
|
||||
with pytest.raises(ArgumentError):
|
||||
kwargs = {**defaults, "index_type": IndexType.RANGE, "pattern": "ABC"}
|
||||
indq.create(**kwargs)
|
||||
kwargs = {**defaults, "index_type": IndexType.RANGE, "pattern": "A-F"}
|
||||
assert indq.create(**kwargs)
|
||||
|
||||
# Prefix indexes require nonempty patterns
|
||||
with pytest.raises(ArgumentError):
|
||||
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": ""}
|
||||
indq.create(**kwargs)
|
||||
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": "Prefix:"}
|
||||
assert indq.create(**kwargs)
|
||||
|
||||
# Etc indexes require nonempty patterns
|
||||
with pytest.raises(ArgumentError):
|
||||
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": ""}
|
||||
indq.create(**kwargs)
|
||||
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": "&c."}
|
||||
assert indq.create(**kwargs)
|
Loading…
Reference in New Issue
Block a user